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 
72238959bSMark Brown #include <kunit/test.h>
82238959bSMark Brown #include "internal.h"
92238959bSMark Brown 
102238959bSMark Brown #define BLOCK_TEST_SIZE 12
112238959bSMark Brown 
get_changed_bytes(void * orig,void * new,size_t size)12*d1b6521cSMark Brown static void get_changed_bytes(void *orig, void *new, size_t size)
13*d1b6521cSMark Brown {
14*d1b6521cSMark Brown 	char *o = orig;
15*d1b6521cSMark Brown 	char *n = new;
16*d1b6521cSMark Brown 	int i;
17*d1b6521cSMark Brown 
18*d1b6521cSMark Brown 	get_random_bytes(new, size);
19*d1b6521cSMark Brown 
20*d1b6521cSMark Brown 	/*
21*d1b6521cSMark Brown 	 * This could be nicer and more efficient but we shouldn't
22*d1b6521cSMark Brown 	 * super care.
23*d1b6521cSMark Brown 	 */
24*d1b6521cSMark Brown 	for (i = 0; i < size; i++)
25*d1b6521cSMark Brown 		while (n[i] == o[i])
26*d1b6521cSMark Brown 			get_random_bytes(&n[i], 1);
27*d1b6521cSMark Brown }
28*d1b6521cSMark Brown 
292238959bSMark Brown static const struct regmap_config test_regmap_config = {
302238959bSMark Brown 	.max_register = BLOCK_TEST_SIZE,
312238959bSMark Brown 	.reg_stride = 1,
322238959bSMark Brown 	.val_bits = sizeof(unsigned int) * 8,
332238959bSMark Brown };
342238959bSMark Brown 
352238959bSMark Brown struct regcache_types {
362238959bSMark Brown 	enum regcache_type type;
372238959bSMark Brown 	const char *name;
382238959bSMark Brown };
392238959bSMark Brown 
case_to_desc(const struct regcache_types * t,char * desc)402238959bSMark Brown static void case_to_desc(const struct regcache_types *t, char *desc)
412238959bSMark Brown {
422238959bSMark Brown 	strcpy(desc, t->name);
432238959bSMark Brown }
442238959bSMark Brown 
452238959bSMark Brown static const struct regcache_types regcache_types_list[] = {
462238959bSMark Brown 	{ REGCACHE_NONE, "none" },
472238959bSMark Brown 	{ REGCACHE_FLAT, "flat" },
482238959bSMark Brown 	{ REGCACHE_RBTREE, "rbtree" },
49f033c26dSMark Brown 	{ REGCACHE_MAPLE, "maple" },
502238959bSMark Brown };
512238959bSMark Brown 
522238959bSMark Brown KUNIT_ARRAY_PARAM(regcache_types, regcache_types_list, case_to_desc);
532238959bSMark Brown 
542238959bSMark Brown static const struct regcache_types real_cache_types_list[] = {
552238959bSMark Brown 	{ REGCACHE_FLAT, "flat" },
562238959bSMark Brown 	{ REGCACHE_RBTREE, "rbtree" },
57f033c26dSMark Brown 	{ REGCACHE_MAPLE, "maple" },
582238959bSMark Brown };
592238959bSMark Brown 
602238959bSMark Brown KUNIT_ARRAY_PARAM(real_cache_types, real_cache_types_list, case_to_desc);
612238959bSMark Brown 
622238959bSMark Brown static const struct regcache_types sparse_cache_types_list[] = {
632238959bSMark Brown 	{ REGCACHE_RBTREE, "rbtree" },
64f033c26dSMark Brown 	{ REGCACHE_MAPLE, "maple" },
652238959bSMark Brown };
662238959bSMark Brown 
672238959bSMark Brown KUNIT_ARRAY_PARAM(sparse_cache_types, sparse_cache_types_list, case_to_desc);
682238959bSMark Brown 
gen_regmap(struct regmap_config * config,struct regmap_ram_data ** data)692238959bSMark Brown static struct regmap *gen_regmap(struct regmap_config *config,
702238959bSMark Brown 				 struct regmap_ram_data **data)
712238959bSMark Brown {
722238959bSMark Brown 	unsigned int *buf;
732238959bSMark Brown 	struct regmap *ret;
742238959bSMark Brown 	size_t size = (config->max_register + 1) * sizeof(unsigned int);
752238959bSMark Brown 	int i;
762238959bSMark Brown 	struct reg_default *defaults;
772238959bSMark Brown 
78a9e26169SGuenter Roeck 	config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
79a9e26169SGuenter Roeck 					config->cache_type == REGCACHE_MAPLE;
80a9e26169SGuenter Roeck 
812238959bSMark Brown 	buf = kmalloc(size, GFP_KERNEL);
822238959bSMark Brown 	if (!buf)
832238959bSMark Brown 		return ERR_PTR(-ENOMEM);
842238959bSMark Brown 
852238959bSMark Brown 	get_random_bytes(buf, size);
862238959bSMark Brown 
872238959bSMark Brown 	*data = kzalloc(sizeof(**data), GFP_KERNEL);
882238959bSMark Brown 	if (!(*data))
892238959bSMark Brown 		return ERR_PTR(-ENOMEM);
902238959bSMark Brown 	(*data)->vals = buf;
912238959bSMark Brown 
922238959bSMark Brown 	if (config->num_reg_defaults) {
932238959bSMark Brown 		defaults = kcalloc(config->num_reg_defaults,
942238959bSMark Brown 				   sizeof(struct reg_default),
952238959bSMark Brown 				   GFP_KERNEL);
962238959bSMark Brown 		if (!defaults)
972238959bSMark Brown 			return ERR_PTR(-ENOMEM);
982238959bSMark Brown 		config->reg_defaults = defaults;
992238959bSMark Brown 
1002238959bSMark Brown 		for (i = 0; i < config->num_reg_defaults; i++) {
1012238959bSMark Brown 			defaults[i].reg = i * config->reg_stride;
1022238959bSMark Brown 			defaults[i].def = buf[i * config->reg_stride];
1032238959bSMark Brown 		}
1042238959bSMark Brown 	}
1052238959bSMark Brown 
1062238959bSMark Brown 	ret = regmap_init_ram(config, *data);
1072238959bSMark Brown 	if (IS_ERR(ret)) {
1082238959bSMark Brown 		kfree(buf);
1092238959bSMark Brown 		kfree(*data);
1102238959bSMark Brown 	}
1112238959bSMark Brown 
1122238959bSMark Brown 	return ret;
1132238959bSMark Brown }
1142238959bSMark Brown 
reg_5_false(struct device * context,unsigned int reg)11518003306SMark Brown static bool reg_5_false(struct device *context, unsigned int reg)
11618003306SMark Brown {
11718003306SMark Brown 	return reg != 5;
11818003306SMark Brown }
11918003306SMark Brown 
basic_read_write(struct kunit * test)1202238959bSMark Brown static void basic_read_write(struct kunit *test)
1212238959bSMark Brown {
1222238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
1232238959bSMark Brown 	struct regmap *map;
1242238959bSMark Brown 	struct regmap_config config;
1252238959bSMark Brown 	struct regmap_ram_data *data;
1262238959bSMark Brown 	unsigned int val, rval;
1272238959bSMark Brown 
1282238959bSMark Brown 	config = test_regmap_config;
1292238959bSMark Brown 	config.cache_type = t->type;
1302238959bSMark Brown 
1312238959bSMark Brown 	map = gen_regmap(&config, &data);
1322238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1332238959bSMark Brown 	if (IS_ERR(map))
1342238959bSMark Brown 		return;
1352238959bSMark Brown 
1362238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
1372238959bSMark Brown 
1382238959bSMark Brown 	/* If we write a value to a register we can read it back */
1392238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
1402238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
1412238959bSMark Brown 	KUNIT_EXPECT_EQ(test, val, rval);
1422238959bSMark Brown 
1432238959bSMark Brown 	/* If using a cache the cache satisfied the read */
1442238959bSMark Brown 	KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE, data->read[0]);
1452238959bSMark Brown 
1462238959bSMark Brown 	regmap_exit(map);
1472238959bSMark Brown }
1482238959bSMark Brown 
bulk_write(struct kunit * test)1492238959bSMark Brown static void bulk_write(struct kunit *test)
1502238959bSMark Brown {
1512238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
1522238959bSMark Brown 	struct regmap *map;
1532238959bSMark Brown 	struct regmap_config config;
1542238959bSMark Brown 	struct regmap_ram_data *data;
1552238959bSMark Brown 	unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
1562238959bSMark Brown 	int i;
1572238959bSMark Brown 
1582238959bSMark Brown 	config = test_regmap_config;
1592238959bSMark Brown 	config.cache_type = t->type;
1602238959bSMark Brown 
1612238959bSMark Brown 	map = gen_regmap(&config, &data);
1622238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1632238959bSMark Brown 	if (IS_ERR(map))
1642238959bSMark Brown 		return;
1652238959bSMark Brown 
1662238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
1672238959bSMark Brown 
1682238959bSMark Brown 	/*
1692238959bSMark Brown 	 * Data written via the bulk API can be read back with single
1702238959bSMark Brown 	 * reads.
1712238959bSMark Brown 	 */
1722238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, 0, val,
1732238959bSMark Brown 						   BLOCK_TEST_SIZE));
1742238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1752238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval[i]));
1762238959bSMark Brown 
1772238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
1782238959bSMark Brown 
1792238959bSMark Brown 	/* If using a cache the cache satisfied the read */
1802238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1812238959bSMark Brown 		KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE, data->read[i]);
1822238959bSMark Brown 
1832238959bSMark Brown 	regmap_exit(map);
1842238959bSMark Brown }
1852238959bSMark Brown 
bulk_read(struct kunit * test)1862238959bSMark Brown static void bulk_read(struct kunit *test)
1872238959bSMark Brown {
1882238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
1892238959bSMark Brown 	struct regmap *map;
1902238959bSMark Brown 	struct regmap_config config;
1912238959bSMark Brown 	struct regmap_ram_data *data;
1922238959bSMark Brown 	unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
1932238959bSMark Brown 	int i;
1942238959bSMark Brown 
1952238959bSMark Brown 	config = test_regmap_config;
1962238959bSMark Brown 	config.cache_type = t->type;
1972238959bSMark Brown 
1982238959bSMark Brown 	map = gen_regmap(&config, &data);
1992238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
2002238959bSMark Brown 	if (IS_ERR(map))
2012238959bSMark Brown 		return;
2022238959bSMark Brown 
2032238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
2042238959bSMark Brown 
2052238959bSMark Brown 	/* Data written as single writes can be read via the bulk API */
2062238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
2072238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, val[i]));
2082238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
2092238959bSMark Brown 						  BLOCK_TEST_SIZE));
2102238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
2112238959bSMark Brown 
2122238959bSMark Brown 	/* If using a cache the cache satisfied the read */
2132238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
2142238959bSMark Brown 		KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE, data->read[i]);
2152238959bSMark Brown 
2162238959bSMark Brown 	regmap_exit(map);
2172238959bSMark Brown }
2182238959bSMark Brown 
write_readonly(struct kunit * test)21918003306SMark Brown static void write_readonly(struct kunit *test)
22018003306SMark Brown {
22118003306SMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
22218003306SMark Brown 	struct regmap *map;
22318003306SMark Brown 	struct regmap_config config;
22418003306SMark Brown 	struct regmap_ram_data *data;
22518003306SMark Brown 	unsigned int val;
22618003306SMark Brown 	int i;
22718003306SMark Brown 
22818003306SMark Brown 	config = test_regmap_config;
22918003306SMark Brown 	config.cache_type = t->type;
23018003306SMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
23118003306SMark Brown 	config.writeable_reg = reg_5_false;
23218003306SMark Brown 
23318003306SMark Brown 	map = gen_regmap(&config, &data);
23418003306SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
23518003306SMark Brown 	if (IS_ERR(map))
23618003306SMark Brown 		return;
23718003306SMark Brown 
23818003306SMark Brown 	get_random_bytes(&val, sizeof(val));
23918003306SMark Brown 
24018003306SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
24118003306SMark Brown 		data->written[i] = false;
24218003306SMark Brown 
24318003306SMark Brown 	/* Change the value of all registers, readonly should fail */
24418003306SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
24518003306SMark Brown 		KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0);
24618003306SMark Brown 
24718003306SMark Brown 	/* Did that match what we see on the device? */
24818003306SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
24918003306SMark Brown 		KUNIT_EXPECT_EQ(test, i != 5, data->written[i]);
25018003306SMark Brown 
25118003306SMark Brown 	regmap_exit(map);
25218003306SMark Brown }
25318003306SMark Brown 
read_writeonly(struct kunit * test)254a07bff40SMark Brown static void read_writeonly(struct kunit *test)
255a07bff40SMark Brown {
256a07bff40SMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
257a07bff40SMark Brown 	struct regmap *map;
258a07bff40SMark Brown 	struct regmap_config config;
259a07bff40SMark Brown 	struct regmap_ram_data *data;
260a07bff40SMark Brown 	unsigned int val;
261a07bff40SMark Brown 	int i;
262a07bff40SMark Brown 
263a07bff40SMark Brown 	config = test_regmap_config;
264a07bff40SMark Brown 	config.cache_type = t->type;
265a07bff40SMark Brown 	config.readable_reg = reg_5_false;
266a07bff40SMark Brown 
267a07bff40SMark Brown 	map = gen_regmap(&config, &data);
268a07bff40SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
269a07bff40SMark Brown 	if (IS_ERR(map))
270a07bff40SMark Brown 		return;
271a07bff40SMark Brown 
272a07bff40SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
273a07bff40SMark Brown 		data->read[i] = false;
274a07bff40SMark Brown 
275d0c99ffeSMark Brown 	/*
276d0c99ffeSMark Brown 	 * Try to read all the registers, the writeonly one should
277d0c99ffeSMark Brown 	 * fail if we aren't using the flat cache.
278d0c99ffeSMark Brown 	 */
279d0c99ffeSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
280d0c99ffeSMark Brown 		if (t->type != REGCACHE_FLAT) {
281d0c99ffeSMark Brown 			KUNIT_EXPECT_EQ(test, i != 5,
282d0c99ffeSMark Brown 					regmap_read(map, i, &val) == 0);
283d0c99ffeSMark Brown 		} else {
284d0c99ffeSMark Brown 			KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
285d0c99ffeSMark Brown 		}
286d0c99ffeSMark Brown 	}
287a07bff40SMark Brown 
288a07bff40SMark Brown 	/* Did we trigger a hardware access? */
289a07bff40SMark Brown 	KUNIT_EXPECT_FALSE(test, data->read[5]);
290a07bff40SMark Brown 
291a07bff40SMark Brown 	regmap_exit(map);
292a07bff40SMark Brown }
293a07bff40SMark Brown 
reg_defaults(struct kunit * test)2942238959bSMark Brown static void reg_defaults(struct kunit *test)
2952238959bSMark Brown {
2962238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
2972238959bSMark Brown 	struct regmap *map;
2982238959bSMark Brown 	struct regmap_config config;
2992238959bSMark Brown 	struct regmap_ram_data *data;
3002238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
3012238959bSMark Brown 	int i;
3022238959bSMark Brown 
3032238959bSMark Brown 	config = test_regmap_config;
3042238959bSMark Brown 	config.cache_type = t->type;
3052238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
3062238959bSMark Brown 
3072238959bSMark Brown 	map = gen_regmap(&config, &data);
3082238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
3092238959bSMark Brown 	if (IS_ERR(map))
3102238959bSMark Brown 		return;
3112238959bSMark Brown 
3122238959bSMark Brown 	/* Read back the expected default data */
3132238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
3142238959bSMark Brown 						  BLOCK_TEST_SIZE));
3152238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, rval, sizeof(rval));
3162238959bSMark Brown 
3172238959bSMark Brown 	/* The data should have been read from cache if there was one */
3182238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
3192238959bSMark Brown 		KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE, data->read[i]);
3202238959bSMark Brown }
3212238959bSMark Brown 
reg_defaults_read_dev(struct kunit * test)3222238959bSMark Brown static void reg_defaults_read_dev(struct kunit *test)
3232238959bSMark Brown {
3242238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
3252238959bSMark Brown 	struct regmap *map;
3262238959bSMark Brown 	struct regmap_config config;
3272238959bSMark Brown 	struct regmap_ram_data *data;
3282238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
3292238959bSMark Brown 	int i;
3302238959bSMark Brown 
3312238959bSMark Brown 	config = test_regmap_config;
3322238959bSMark Brown 	config.cache_type = t->type;
3332238959bSMark Brown 	config.num_reg_defaults_raw = BLOCK_TEST_SIZE;
3342238959bSMark Brown 
3352238959bSMark Brown 	map = gen_regmap(&config, &data);
3362238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
3372238959bSMark Brown 	if (IS_ERR(map))
3382238959bSMark Brown 		return;
3392238959bSMark Brown 
3402238959bSMark Brown 	/* We should have read the cache defaults back from the map */
3412238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
3422238959bSMark Brown 		KUNIT_EXPECT_EQ(test, t->type != REGCACHE_NONE, data->read[i]);
3432238959bSMark Brown 		data->read[i] = false;
3442238959bSMark Brown 	}
3452238959bSMark Brown 
3462238959bSMark Brown 	/* Read back the expected default data */
3472238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
3482238959bSMark Brown 						  BLOCK_TEST_SIZE));
3492238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, rval, sizeof(rval));
3502238959bSMark Brown 
3512238959bSMark Brown 	/* The data should have been read from cache if there was one */
3522238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
3532238959bSMark Brown 		KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE, data->read[i]);
3542238959bSMark Brown }
3552238959bSMark Brown 
register_patch(struct kunit * test)3562238959bSMark Brown static void register_patch(struct kunit *test)
3572238959bSMark Brown {
3582238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
3592238959bSMark Brown 	struct regmap *map;
3602238959bSMark Brown 	struct regmap_config config;
3612238959bSMark Brown 	struct regmap_ram_data *data;
3622238959bSMark Brown 	struct reg_sequence patch[2];
3632238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
3642238959bSMark Brown 	int i;
3652238959bSMark Brown 
3662238959bSMark Brown 	/* We need defaults so readback works */
3672238959bSMark Brown 	config = test_regmap_config;
3682238959bSMark Brown 	config.cache_type = t->type;
3692238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
3702238959bSMark Brown 
3712238959bSMark Brown 	map = gen_regmap(&config, &data);
3722238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
3732238959bSMark Brown 	if (IS_ERR(map))
3742238959bSMark Brown 		return;
3752238959bSMark Brown 
3762238959bSMark Brown 	/* Stash the original values */
3772238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
3782238959bSMark Brown 						  BLOCK_TEST_SIZE));
3792238959bSMark Brown 
3802238959bSMark Brown 	/* Patch a couple of values */
3812238959bSMark Brown 	patch[0].reg = 2;
3822238959bSMark Brown 	patch[0].def = rval[2] + 1;
3832238959bSMark Brown 	patch[0].delay_us = 0;
3842238959bSMark Brown 	patch[1].reg = 5;
3852238959bSMark Brown 	patch[1].def = rval[5] + 1;
3862238959bSMark Brown 	patch[1].delay_us = 0;
3872238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_register_patch(map, patch,
3882238959bSMark Brown 						       ARRAY_SIZE(patch)));
3892238959bSMark Brown 
3902238959bSMark Brown 	/* Only the patched registers are written */
3912238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
3922238959bSMark Brown 		switch (i) {
3932238959bSMark Brown 		case 2:
3942238959bSMark Brown 		case 5:
3952238959bSMark Brown 			KUNIT_EXPECT_TRUE(test, data->written[i]);
3962238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval[i] + 1);
3972238959bSMark Brown 			break;
3982238959bSMark Brown 		default:
3992238959bSMark Brown 			KUNIT_EXPECT_FALSE(test, data->written[i]);
4002238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval[i]);
4012238959bSMark Brown 			break;
4022238959bSMark Brown 		}
4032238959bSMark Brown 	}
4042238959bSMark Brown 
4052238959bSMark Brown 	regmap_exit(map);
4062238959bSMark Brown }
4072238959bSMark Brown 
stride(struct kunit * test)4082238959bSMark Brown static void stride(struct kunit *test)
4092238959bSMark Brown {
4102238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
4112238959bSMark Brown 	struct regmap *map;
4122238959bSMark Brown 	struct regmap_config config;
4132238959bSMark Brown 	struct regmap_ram_data *data;
4142238959bSMark Brown 	unsigned int rval;
4152238959bSMark Brown 	int i;
4162238959bSMark Brown 
4172238959bSMark Brown 	config = test_regmap_config;
4182238959bSMark Brown 	config.cache_type = t->type;
4192238959bSMark Brown 	config.reg_stride = 2;
4202238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE / 2;
4212238959bSMark Brown 
4222238959bSMark Brown 	map = gen_regmap(&config, &data);
4232238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
4242238959bSMark Brown 	if (IS_ERR(map))
4252238959bSMark Brown 		return;
4262238959bSMark Brown 
4272238959bSMark Brown 	/* Only even registers can be accessed, try both read and write */
4282238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
4292238959bSMark Brown 		data->read[i] = false;
4302238959bSMark Brown 		data->written[i] = false;
4312238959bSMark Brown 
4322238959bSMark Brown 		if (i % 2) {
4332238959bSMark Brown 			KUNIT_EXPECT_NE(test, 0, regmap_read(map, i, &rval));
4342238959bSMark Brown 			KUNIT_EXPECT_NE(test, 0, regmap_write(map, i, rval));
4352238959bSMark Brown 			KUNIT_EXPECT_FALSE(test, data->read[i]);
4362238959bSMark Brown 			KUNIT_EXPECT_FALSE(test, data->written[i]);
4372238959bSMark Brown 		} else {
4382238959bSMark Brown 			KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
4392238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval);
4402238959bSMark Brown 			KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE,
4412238959bSMark Brown 					data->read[i]);
4422238959bSMark Brown 
4432238959bSMark Brown 			KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, rval));
4442238959bSMark Brown 			KUNIT_EXPECT_TRUE(test, data->written[i]);
4452238959bSMark Brown 		}
4462238959bSMark Brown 	}
4472238959bSMark Brown 
4482238959bSMark Brown 	regmap_exit(map);
4492238959bSMark Brown }
4502238959bSMark Brown 
4512238959bSMark Brown static struct regmap_range_cfg test_range = {
4522238959bSMark Brown 	.selector_reg = 1,
4532238959bSMark Brown 	.selector_mask = 0xff,
4542238959bSMark Brown 
4552238959bSMark Brown 	.window_start = 4,
4562238959bSMark Brown 	.window_len = 10,
4572238959bSMark Brown 
4582238959bSMark Brown 	.range_min = 20,
4592238959bSMark Brown 	.range_max = 40,
4602238959bSMark Brown };
4612238959bSMark Brown 
test_range_volatile(struct device * dev,unsigned int reg)4622238959bSMark Brown static bool test_range_volatile(struct device *dev, unsigned int reg)
4632238959bSMark Brown {
4642238959bSMark Brown 	if (reg >= test_range.window_start &&
4652238959bSMark Brown 	    reg <= test_range.selector_reg + test_range.window_len)
4662238959bSMark Brown 		return true;
4672238959bSMark Brown 
4682238959bSMark Brown 	if (reg >= test_range.range_min && reg <= test_range.range_max)
4692238959bSMark Brown 		return true;
4702238959bSMark Brown 
4712238959bSMark Brown 	return false;
4722238959bSMark Brown }
4732238959bSMark Brown 
basic_ranges(struct kunit * test)4742238959bSMark Brown static void basic_ranges(struct kunit *test)
4752238959bSMark Brown {
4762238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
4772238959bSMark Brown 	struct regmap *map;
4782238959bSMark Brown 	struct regmap_config config;
4792238959bSMark Brown 	struct regmap_ram_data *data;
4802238959bSMark Brown 	unsigned int val;
4812238959bSMark Brown 	int i;
4822238959bSMark Brown 
4832238959bSMark Brown 	config = test_regmap_config;
4842238959bSMark Brown 	config.cache_type = t->type;
4852238959bSMark Brown 	config.volatile_reg = test_range_volatile;
4862238959bSMark Brown 	config.ranges = &test_range;
4872238959bSMark Brown 	config.num_ranges = 1;
4882238959bSMark Brown 	config.max_register = test_range.range_max;
4892238959bSMark Brown 
4902238959bSMark Brown 	map = gen_regmap(&config, &data);
4912238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
4922238959bSMark Brown 	if (IS_ERR(map))
4932238959bSMark Brown 		return;
4942238959bSMark Brown 
4952238959bSMark Brown 	for (i = test_range.range_min; i < test_range.range_max; i++) {
4962238959bSMark Brown 		data->read[i] = false;
4972238959bSMark Brown 		data->written[i] = false;
4982238959bSMark Brown 	}
4992238959bSMark Brown 
5002238959bSMark Brown 	/* Reset the page to a non-zero value to trigger a change */
5012238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.selector_reg,
5022238959bSMark Brown 					      test_range.range_max));
5032238959bSMark Brown 
5042238959bSMark Brown 	/* Check we set the page and use the window for writes */
5052238959bSMark Brown 	data->written[test_range.selector_reg] = false;
5062238959bSMark Brown 	data->written[test_range.window_start] = false;
5072238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
5082238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
5092238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
5102238959bSMark Brown 
5112238959bSMark Brown 	data->written[test_range.selector_reg] = false;
5122238959bSMark Brown 	data->written[test_range.window_start] = false;
5132238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map,
5142238959bSMark Brown 					      test_range.range_min +
5152238959bSMark Brown 					      test_range.window_len,
5162238959bSMark Brown 					      0));
5172238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
5182238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
5192238959bSMark Brown 
5202238959bSMark Brown 	/* Same for reads */
5212238959bSMark Brown 	data->written[test_range.selector_reg] = false;
5222238959bSMark Brown 	data->read[test_range.window_start] = false;
5232238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, test_range.range_min, &val));
5242238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
5252238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
5262238959bSMark Brown 
5272238959bSMark Brown 	data->written[test_range.selector_reg] = false;
5282238959bSMark Brown 	data->read[test_range.window_start] = false;
5292238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map,
5302238959bSMark Brown 					     test_range.range_min +
5312238959bSMark Brown 					     test_range.window_len,
5322238959bSMark Brown 					     &val));
5332238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
5342238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
5352238959bSMark Brown 
5362238959bSMark Brown 	/* No physical access triggered in the virtual range */
5372238959bSMark Brown 	for (i = test_range.range_min; i < test_range.range_max; i++) {
5382238959bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->read[i]);
5392238959bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->written[i]);
5402238959bSMark Brown 	}
5412238959bSMark Brown 
5422238959bSMark Brown 	regmap_exit(map);
5432238959bSMark Brown }
5442238959bSMark Brown 
5452238959bSMark Brown /* Try to stress dynamic creation of cache data structures */
stress_insert(struct kunit * test)5462238959bSMark Brown static void stress_insert(struct kunit *test)
5472238959bSMark Brown {
5482238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
5492238959bSMark Brown 	struct regmap *map;
5502238959bSMark Brown 	struct regmap_config config;
5512238959bSMark Brown 	struct regmap_ram_data *data;
5522238959bSMark Brown 	unsigned int rval, *vals;
5532238959bSMark Brown 	size_t buf_sz;
5542238959bSMark Brown 	int i;
5552238959bSMark Brown 
5562238959bSMark Brown 	config = test_regmap_config;
5572238959bSMark Brown 	config.cache_type = t->type;
5582238959bSMark Brown 	config.max_register = 300;
5592238959bSMark Brown 
5602238959bSMark Brown 	map = gen_regmap(&config, &data);
5612238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
5622238959bSMark Brown 	if (IS_ERR(map))
5632238959bSMark Brown 		return;
5642238959bSMark Brown 
5652238959bSMark Brown 	vals = kunit_kcalloc(test, sizeof(unsigned long), config.max_register,
5662238959bSMark Brown 			     GFP_KERNEL);
5672238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, vals == NULL);
5682238959bSMark Brown 	buf_sz = sizeof(unsigned long) * config.max_register;
5692238959bSMark Brown 
5702238959bSMark Brown 	get_random_bytes(vals, buf_sz);
5712238959bSMark Brown 
5722238959bSMark Brown 	/* Write data into the map/cache in ever decreasing strides */
5732238959bSMark Brown 	for (i = 0; i < config.max_register; i += 100)
5742238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5752238959bSMark Brown 	for (i = 0; i < config.max_register; i += 50)
5762238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5772238959bSMark Brown 	for (i = 0; i < config.max_register; i += 25)
5782238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5792238959bSMark Brown 	for (i = 0; i < config.max_register; i += 10)
5802238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5812238959bSMark Brown 	for (i = 0; i < config.max_register; i += 5)
5822238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5832238959bSMark Brown 	for (i = 0; i < config.max_register; i += 3)
5842238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5852238959bSMark Brown 	for (i = 0; i < config.max_register; i += 2)
5862238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5872238959bSMark Brown 	for (i = 0; i < config.max_register; i++)
5882238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
5892238959bSMark Brown 
5902238959bSMark Brown 	/* Do reads from the cache (if there is one) match? */
5912238959bSMark Brown 	for (i = 0; i < config.max_register; i ++) {
5922238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
5932238959bSMark Brown 		KUNIT_EXPECT_EQ(test, rval, vals[i]);
5942238959bSMark Brown 		KUNIT_EXPECT_EQ(test, t->type == REGCACHE_NONE, data->read[i]);
5952238959bSMark Brown 	}
5962238959bSMark Brown 
5972238959bSMark Brown 	regmap_exit(map);
5982238959bSMark Brown }
5992238959bSMark Brown 
cache_bypass(struct kunit * test)6002238959bSMark Brown static void cache_bypass(struct kunit *test)
6012238959bSMark Brown {
6022238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
6032238959bSMark Brown 	struct regmap *map;
6042238959bSMark Brown 	struct regmap_config config;
6052238959bSMark Brown 	struct regmap_ram_data *data;
6062238959bSMark Brown 	unsigned int val, rval;
6072238959bSMark Brown 
6082238959bSMark Brown 	config = test_regmap_config;
6092238959bSMark Brown 	config.cache_type = t->type;
6102238959bSMark Brown 
6112238959bSMark Brown 	map = gen_regmap(&config, &data);
6122238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
6132238959bSMark Brown 	if (IS_ERR(map))
6142238959bSMark Brown 		return;
6152238959bSMark Brown 
6162238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
6172238959bSMark Brown 
6182238959bSMark Brown 	/* Ensure the cache has a value in it */
6192238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
6202238959bSMark Brown 
6212238959bSMark Brown 	/* Bypass then write a different value */
6222238959bSMark Brown 	regcache_cache_bypass(map, true);
6232238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val + 1));
6242238959bSMark Brown 
6252238959bSMark Brown 	/* Read the bypassed value */
6262238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
6272238959bSMark Brown 	KUNIT_EXPECT_EQ(test, val + 1, rval);
6282238959bSMark Brown 	KUNIT_EXPECT_EQ(test, data->vals[0], rval);
6292238959bSMark Brown 
6302238959bSMark Brown 	/* Disable bypass, the cache should still return the original value */
6312238959bSMark Brown 	regcache_cache_bypass(map, false);
6322238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
6332238959bSMark Brown 	KUNIT_EXPECT_EQ(test, val, rval);
6342238959bSMark Brown 
6352238959bSMark Brown 	regmap_exit(map);
6362238959bSMark Brown }
6372238959bSMark Brown 
cache_sync(struct kunit * test)6382238959bSMark Brown static void cache_sync(struct kunit *test)
6392238959bSMark Brown {
6402238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
6412238959bSMark Brown 	struct regmap *map;
6422238959bSMark Brown 	struct regmap_config config;
6432238959bSMark Brown 	struct regmap_ram_data *data;
6442238959bSMark Brown 	unsigned int val[BLOCK_TEST_SIZE];
6452238959bSMark Brown 	int i;
6462238959bSMark Brown 
6472238959bSMark Brown 	config = test_regmap_config;
6482238959bSMark Brown 	config.cache_type = t->type;
6492238959bSMark Brown 
6502238959bSMark Brown 	map = gen_regmap(&config, &data);
6512238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
6522238959bSMark Brown 	if (IS_ERR(map))
6532238959bSMark Brown 		return;
6542238959bSMark Brown 
6552238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
6562238959bSMark Brown 
6572238959bSMark Brown 	/* Put some data into the cache */
6582238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, 0, val,
6592238959bSMark Brown 						   BLOCK_TEST_SIZE));
6602238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
6612238959bSMark Brown 		data->written[i] = false;
6622238959bSMark Brown 
6632238959bSMark Brown 	/* Trash the data on the device itself then resync */
6642238959bSMark Brown 	regcache_mark_dirty(map);
6652238959bSMark Brown 	memset(data->vals, 0, sizeof(val));
6662238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
6672238959bSMark Brown 
6682238959bSMark Brown 	/* Did we just write the correct data out? */
6692238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, val, sizeof(val));
6702238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
6712238959bSMark Brown 		KUNIT_EXPECT_EQ(test, true, data->written[i]);
6722238959bSMark Brown 
6732238959bSMark Brown 	regmap_exit(map);
6742238959bSMark Brown }
6752238959bSMark Brown 
cache_sync_defaults(struct kunit * test)6762238959bSMark Brown static void cache_sync_defaults(struct kunit *test)
6772238959bSMark Brown {
6782238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
6792238959bSMark Brown 	struct regmap *map;
6802238959bSMark Brown 	struct regmap_config config;
6812238959bSMark Brown 	struct regmap_ram_data *data;
6822238959bSMark Brown 	unsigned int val;
6832238959bSMark Brown 	int i;
6842238959bSMark Brown 
6852238959bSMark Brown 	config = test_regmap_config;
6862238959bSMark Brown 	config.cache_type = t->type;
6872238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
6882238959bSMark Brown 
6892238959bSMark Brown 	map = gen_regmap(&config, &data);
6902238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
6912238959bSMark Brown 	if (IS_ERR(map))
6922238959bSMark Brown 		return;
6932238959bSMark Brown 
6942238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
6952238959bSMark Brown 
6962238959bSMark Brown 	/* Change the value of one register */
6972238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 2, val));
6982238959bSMark Brown 
6992238959bSMark Brown 	/* Resync */
7002238959bSMark Brown 	regcache_mark_dirty(map);
7012238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
7022238959bSMark Brown 		data->written[i] = false;
7032238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
7042238959bSMark Brown 
7052238959bSMark Brown 	/* Did we just sync the one register we touched? */
7062238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
7072238959bSMark Brown 		KUNIT_EXPECT_EQ(test, i == 2, data->written[i]);
7082238959bSMark Brown 
7092238959bSMark Brown 	regmap_exit(map);
7102238959bSMark Brown }
7112238959bSMark Brown 
cache_sync_readonly(struct kunit * test)712357a1ebdSMark Brown static void cache_sync_readonly(struct kunit *test)
713357a1ebdSMark Brown {
714357a1ebdSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
715357a1ebdSMark Brown 	struct regmap *map;
716357a1ebdSMark Brown 	struct regmap_config config;
717357a1ebdSMark Brown 	struct regmap_ram_data *data;
718357a1ebdSMark Brown 	unsigned int val;
719357a1ebdSMark Brown 	int i;
720357a1ebdSMark Brown 
721357a1ebdSMark Brown 	config = test_regmap_config;
722357a1ebdSMark Brown 	config.cache_type = t->type;
723357a1ebdSMark Brown 	config.writeable_reg = reg_5_false;
724357a1ebdSMark Brown 
725357a1ebdSMark Brown 	map = gen_regmap(&config, &data);
726357a1ebdSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
727357a1ebdSMark Brown 	if (IS_ERR(map))
728357a1ebdSMark Brown 		return;
729357a1ebdSMark Brown 
730357a1ebdSMark Brown 	/* Read all registers to fill the cache */
731357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
732357a1ebdSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
733357a1ebdSMark Brown 
734357a1ebdSMark Brown 	/* Change the value of all registers, readonly should fail */
735357a1ebdSMark Brown 	get_random_bytes(&val, sizeof(val));
736357a1ebdSMark Brown 	regcache_cache_only(map, true);
737357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
738357a1ebdSMark Brown 		KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0);
739357a1ebdSMark Brown 	regcache_cache_only(map, false);
740357a1ebdSMark Brown 
741357a1ebdSMark Brown 	/* Resync */
742357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
743357a1ebdSMark Brown 		data->written[i] = false;
744357a1ebdSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
745357a1ebdSMark Brown 
746357a1ebdSMark Brown 	/* Did that match what we see on the device? */
747357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
748357a1ebdSMark Brown 		KUNIT_EXPECT_EQ(test, i != 5, data->written[i]);
749357a1ebdSMark Brown 
750357a1ebdSMark Brown 	regmap_exit(map);
751357a1ebdSMark Brown }
752357a1ebdSMark Brown 
cache_sync_patch(struct kunit * test)7532238959bSMark Brown static void cache_sync_patch(struct kunit *test)
7542238959bSMark Brown {
7552238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
7562238959bSMark Brown 	struct regmap *map;
7572238959bSMark Brown 	struct regmap_config config;
7582238959bSMark Brown 	struct regmap_ram_data *data;
7592238959bSMark Brown 	struct reg_sequence patch[2];
7602238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE], val;
7612238959bSMark Brown 	int i;
7622238959bSMark Brown 
7632238959bSMark Brown 	/* We need defaults so readback works */
7642238959bSMark Brown 	config = test_regmap_config;
7652238959bSMark Brown 	config.cache_type = t->type;
7662238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
7672238959bSMark Brown 
7682238959bSMark Brown 	map = gen_regmap(&config, &data);
7692238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
7702238959bSMark Brown 	if (IS_ERR(map))
7712238959bSMark Brown 		return;
7722238959bSMark Brown 
7732238959bSMark Brown 	/* Stash the original values */
7742238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
7752238959bSMark Brown 						  BLOCK_TEST_SIZE));
7762238959bSMark Brown 
7772238959bSMark Brown 	/* Patch a couple of values */
7782238959bSMark Brown 	patch[0].reg = 2;
7792238959bSMark Brown 	patch[0].def = rval[2] + 1;
7802238959bSMark Brown 	patch[0].delay_us = 0;
7812238959bSMark Brown 	patch[1].reg = 5;
7822238959bSMark Brown 	patch[1].def = rval[5] + 1;
7832238959bSMark Brown 	patch[1].delay_us = 0;
7842238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_register_patch(map, patch,
7852238959bSMark Brown 						       ARRAY_SIZE(patch)));
7862238959bSMark Brown 
7872238959bSMark Brown 	/* Sync the cache */
7882238959bSMark Brown 	regcache_mark_dirty(map);
7892238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
7902238959bSMark Brown 		data->written[i] = false;
7912238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
7922238959bSMark Brown 
7932238959bSMark Brown 	/* The patch should be on the device but not in the cache */
7942238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
7952238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
7962238959bSMark Brown 		KUNIT_EXPECT_EQ(test, val, rval[i]);
7972238959bSMark Brown 
7982238959bSMark Brown 		switch (i) {
7992238959bSMark Brown 		case 2:
8002238959bSMark Brown 		case 5:
8012238959bSMark Brown 			KUNIT_EXPECT_EQ(test, true, data->written[i]);
8022238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval[i] + 1);
8032238959bSMark Brown 			break;
8042238959bSMark Brown 		default:
8052238959bSMark Brown 			KUNIT_EXPECT_EQ(test, false, data->written[i]);
8062238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval[i]);
8072238959bSMark Brown 			break;
8082238959bSMark Brown 		}
8092238959bSMark Brown 	}
8102238959bSMark Brown 
8112238959bSMark Brown 	regmap_exit(map);
8122238959bSMark Brown }
8132238959bSMark Brown 
cache_drop(struct kunit * test)8142238959bSMark Brown static void cache_drop(struct kunit *test)
8152238959bSMark Brown {
8162238959bSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
8172238959bSMark Brown 	struct regmap *map;
8182238959bSMark Brown 	struct regmap_config config;
8192238959bSMark Brown 	struct regmap_ram_data *data;
8202238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
8212238959bSMark Brown 	int i;
8222238959bSMark Brown 
8232238959bSMark Brown 	config = test_regmap_config;
8242238959bSMark Brown 	config.cache_type = t->type;
8252238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
8262238959bSMark Brown 
8272238959bSMark Brown 	map = gen_regmap(&config, &data);
8282238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
8292238959bSMark Brown 	if (IS_ERR(map))
8302238959bSMark Brown 		return;
8312238959bSMark Brown 
8322238959bSMark Brown 	/* Ensure the data is read from the cache */
8332238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
8342238959bSMark Brown 		data->read[i] = false;
8352238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
8362238959bSMark Brown 						  BLOCK_TEST_SIZE));
8372238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
8382238959bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->read[i]);
8392238959bSMark Brown 		data->read[i] = false;
8402238959bSMark Brown 	}
8412238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, rval, sizeof(rval));
8422238959bSMark Brown 
8432238959bSMark Brown 	/* Drop some registers */
8442238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, 3, 5));
8452238959bSMark Brown 
8462238959bSMark Brown 	/* Reread and check only the dropped registers hit the device. */
8472238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
8482238959bSMark Brown 						  BLOCK_TEST_SIZE));
8492238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
8502238959bSMark Brown 		KUNIT_EXPECT_EQ(test, data->read[i], i >= 3 && i <= 5);
8512238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, rval, sizeof(rval));
8522238959bSMark Brown 
8532238959bSMark Brown 	regmap_exit(map);
8542238959bSMark Brown }
8552238959bSMark Brown 
cache_present(struct kunit * test)856d881ee5aSMark Brown static void cache_present(struct kunit *test)
857d881ee5aSMark Brown {
858d881ee5aSMark Brown 	struct regcache_types *t = (struct regcache_types *)test->param_value;
859d881ee5aSMark Brown 	struct regmap *map;
860d881ee5aSMark Brown 	struct regmap_config config;
861d881ee5aSMark Brown 	struct regmap_ram_data *data;
862d881ee5aSMark Brown 	unsigned int val;
863d881ee5aSMark Brown 	int i;
864d881ee5aSMark Brown 
865d881ee5aSMark Brown 	config = test_regmap_config;
866d881ee5aSMark Brown 	config.cache_type = t->type;
867d881ee5aSMark Brown 
868d881ee5aSMark Brown 	map = gen_regmap(&config, &data);
869d881ee5aSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
870d881ee5aSMark Brown 	if (IS_ERR(map))
871d881ee5aSMark Brown 		return;
872d881ee5aSMark Brown 
873d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
874d881ee5aSMark Brown 		data->read[i] = false;
875d881ee5aSMark Brown 
876d881ee5aSMark Brown 	/* No defaults so no registers cached. */
877d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
878d881ee5aSMark Brown 		KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, i));
879d881ee5aSMark Brown 
880d881ee5aSMark Brown 	/* We didn't trigger any reads */
881d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
882d881ee5aSMark Brown 		KUNIT_ASSERT_FALSE(test, data->read[i]);
883d881ee5aSMark Brown 
884d881ee5aSMark Brown 	/* Fill the cache */
885d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
886d881ee5aSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
887d881ee5aSMark Brown 
888d881ee5aSMark Brown 	/* Now everything should be cached */
889d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
890d881ee5aSMark Brown 		KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, i));
891d881ee5aSMark Brown 
892d881ee5aSMark Brown 	regmap_exit(map);
893d881ee5aSMark Brown }
894d881ee5aSMark Brown 
895155a6bd6SMark Brown struct raw_test_types {
896155a6bd6SMark Brown 	const char *name;
897155a6bd6SMark Brown 
898155a6bd6SMark Brown 	enum regcache_type cache_type;
899155a6bd6SMark Brown 	enum regmap_endian val_endian;
900155a6bd6SMark Brown };
901155a6bd6SMark Brown 
raw_to_desc(const struct raw_test_types * t,char * desc)902155a6bd6SMark Brown static void raw_to_desc(const struct raw_test_types *t, char *desc)
903155a6bd6SMark Brown {
904155a6bd6SMark Brown 	strcpy(desc, t->name);
905155a6bd6SMark Brown }
906155a6bd6SMark Brown 
907155a6bd6SMark Brown static const struct raw_test_types raw_types_list[] = {
908155a6bd6SMark Brown 	{ "none-little",   REGCACHE_NONE,   REGMAP_ENDIAN_LITTLE },
909155a6bd6SMark Brown 	{ "none-big",      REGCACHE_NONE,   REGMAP_ENDIAN_BIG },
910155a6bd6SMark Brown 	{ "flat-little",   REGCACHE_FLAT,   REGMAP_ENDIAN_LITTLE },
911155a6bd6SMark Brown 	{ "flat-big",      REGCACHE_FLAT,   REGMAP_ENDIAN_BIG },
912155a6bd6SMark Brown 	{ "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE },
913155a6bd6SMark Brown 	{ "rbtree-big",    REGCACHE_RBTREE, REGMAP_ENDIAN_BIG },
914155a6bd6SMark Brown 	{ "maple-little",  REGCACHE_MAPLE,  REGMAP_ENDIAN_LITTLE },
915155a6bd6SMark Brown 	{ "maple-big",     REGCACHE_MAPLE,  REGMAP_ENDIAN_BIG },
916155a6bd6SMark Brown };
917155a6bd6SMark Brown 
918155a6bd6SMark Brown KUNIT_ARRAY_PARAM(raw_test_types, raw_types_list, raw_to_desc);
919155a6bd6SMark Brown 
920155a6bd6SMark Brown static const struct raw_test_types raw_cache_types_list[] = {
921155a6bd6SMark Brown 	{ "flat-little",   REGCACHE_FLAT,   REGMAP_ENDIAN_LITTLE },
922155a6bd6SMark Brown 	{ "flat-big",      REGCACHE_FLAT,   REGMAP_ENDIAN_BIG },
923155a6bd6SMark Brown 	{ "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE },
924155a6bd6SMark Brown 	{ "rbtree-big",    REGCACHE_RBTREE, REGMAP_ENDIAN_BIG },
925155a6bd6SMark Brown 	{ "maple-little",  REGCACHE_MAPLE,  REGMAP_ENDIAN_LITTLE },
926155a6bd6SMark Brown 	{ "maple-big",     REGCACHE_MAPLE,  REGMAP_ENDIAN_BIG },
927155a6bd6SMark Brown };
928155a6bd6SMark Brown 
929155a6bd6SMark Brown KUNIT_ARRAY_PARAM(raw_test_cache_types, raw_cache_types_list, raw_to_desc);
930155a6bd6SMark Brown 
931155a6bd6SMark Brown static const struct regmap_config raw_regmap_config = {
932155a6bd6SMark Brown 	.max_register = BLOCK_TEST_SIZE,
933155a6bd6SMark Brown 
934155a6bd6SMark Brown 	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
935155a6bd6SMark Brown 	.reg_bits = 16,
936155a6bd6SMark Brown 	.val_bits = 16,
937155a6bd6SMark Brown };
938155a6bd6SMark Brown 
gen_raw_regmap(struct regmap_config * config,struct raw_test_types * test_type,struct regmap_ram_data ** data)939155a6bd6SMark Brown static struct regmap *gen_raw_regmap(struct regmap_config *config,
940155a6bd6SMark Brown 				     struct raw_test_types *test_type,
941155a6bd6SMark Brown 				     struct regmap_ram_data **data)
942155a6bd6SMark Brown {
943155a6bd6SMark Brown 	u16 *buf;
944155a6bd6SMark Brown 	struct regmap *ret;
945155a6bd6SMark Brown 	size_t size = (config->max_register + 1) * config->reg_bits / 8;
946155a6bd6SMark Brown 	int i;
947155a6bd6SMark Brown 	struct reg_default *defaults;
948155a6bd6SMark Brown 
949155a6bd6SMark Brown 	config->cache_type = test_type->cache_type;
950155a6bd6SMark Brown 	config->val_format_endian = test_type->val_endian;
951a9e26169SGuenter Roeck 	config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
952a9e26169SGuenter Roeck 					config->cache_type == REGCACHE_MAPLE;
953155a6bd6SMark Brown 
954155a6bd6SMark Brown 	buf = kmalloc(size, GFP_KERNEL);
955155a6bd6SMark Brown 	if (!buf)
956155a6bd6SMark Brown 		return ERR_PTR(-ENOMEM);
957155a6bd6SMark Brown 
958155a6bd6SMark Brown 	get_random_bytes(buf, size);
959155a6bd6SMark Brown 
960155a6bd6SMark Brown 	*data = kzalloc(sizeof(**data), GFP_KERNEL);
961155a6bd6SMark Brown 	if (!(*data))
962155a6bd6SMark Brown 		return ERR_PTR(-ENOMEM);
963155a6bd6SMark Brown 	(*data)->vals = (void *)buf;
964155a6bd6SMark Brown 
965155a6bd6SMark Brown 	config->num_reg_defaults = config->max_register + 1;
966155a6bd6SMark Brown 	defaults = kcalloc(config->num_reg_defaults,
967155a6bd6SMark Brown 			   sizeof(struct reg_default),
968155a6bd6SMark Brown 			   GFP_KERNEL);
969155a6bd6SMark Brown 	if (!defaults)
970155a6bd6SMark Brown 		return ERR_PTR(-ENOMEM);
971155a6bd6SMark Brown 	config->reg_defaults = defaults;
972155a6bd6SMark Brown 
973155a6bd6SMark Brown 	for (i = 0; i < config->num_reg_defaults; i++) {
974155a6bd6SMark Brown 		defaults[i].reg = i;
975155a6bd6SMark Brown 		switch (test_type->val_endian) {
976155a6bd6SMark Brown 		case REGMAP_ENDIAN_LITTLE:
977155a6bd6SMark Brown 			defaults[i].def = le16_to_cpu(buf[i]);
978155a6bd6SMark Brown 			break;
979155a6bd6SMark Brown 		case REGMAP_ENDIAN_BIG:
980155a6bd6SMark Brown 			defaults[i].def = be16_to_cpu(buf[i]);
981155a6bd6SMark Brown 			break;
982155a6bd6SMark Brown 		default:
983155a6bd6SMark Brown 			return ERR_PTR(-EINVAL);
984155a6bd6SMark Brown 		}
985155a6bd6SMark Brown 	}
986155a6bd6SMark Brown 
987155a6bd6SMark Brown 	/*
988155a6bd6SMark Brown 	 * We use the defaults in the tests but they don't make sense
989155a6bd6SMark Brown 	 * to the core if there's no cache.
990155a6bd6SMark Brown 	 */
991155a6bd6SMark Brown 	if (config->cache_type == REGCACHE_NONE)
992155a6bd6SMark Brown 		config->num_reg_defaults = 0;
993155a6bd6SMark Brown 
994155a6bd6SMark Brown 	ret = regmap_init_raw_ram(config, *data);
995155a6bd6SMark Brown 	if (IS_ERR(ret)) {
996155a6bd6SMark Brown 		kfree(buf);
997155a6bd6SMark Brown 		kfree(*data);
998155a6bd6SMark Brown 	}
999155a6bd6SMark Brown 
1000155a6bd6SMark Brown 	return ret;
1001155a6bd6SMark Brown }
1002155a6bd6SMark Brown 
raw_read_defaults_single(struct kunit * test)1003155a6bd6SMark Brown static void raw_read_defaults_single(struct kunit *test)
1004155a6bd6SMark Brown {
1005155a6bd6SMark Brown 	struct raw_test_types *t = (struct raw_test_types *)test->param_value;
1006155a6bd6SMark Brown 	struct regmap *map;
1007155a6bd6SMark Brown 	struct regmap_config config;
1008155a6bd6SMark Brown 	struct regmap_ram_data *data;
1009155a6bd6SMark Brown 	unsigned int rval;
1010155a6bd6SMark Brown 	int i;
1011155a6bd6SMark Brown 
1012155a6bd6SMark Brown 	config = raw_regmap_config;
1013155a6bd6SMark Brown 
1014155a6bd6SMark Brown 	map = gen_raw_regmap(&config, t, &data);
1015155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1016155a6bd6SMark Brown 	if (IS_ERR(map))
1017155a6bd6SMark Brown 		return;
1018155a6bd6SMark Brown 
1019155a6bd6SMark Brown 	/* Check that we can read the defaults via the API */
1020155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1021155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
1022155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1023155a6bd6SMark Brown 	}
1024155a6bd6SMark Brown 
1025155a6bd6SMark Brown 	regmap_exit(map);
1026155a6bd6SMark Brown }
1027155a6bd6SMark Brown 
raw_read_defaults(struct kunit * test)1028155a6bd6SMark Brown static void raw_read_defaults(struct kunit *test)
1029155a6bd6SMark Brown {
1030155a6bd6SMark Brown 	struct raw_test_types *t = (struct raw_test_types *)test->param_value;
1031155a6bd6SMark Brown 	struct regmap *map;
1032155a6bd6SMark Brown 	struct regmap_config config;
1033155a6bd6SMark Brown 	struct regmap_ram_data *data;
1034155a6bd6SMark Brown 	u16 *rval;
1035155a6bd6SMark Brown 	u16 def;
1036155a6bd6SMark Brown 	size_t val_len;
1037155a6bd6SMark Brown 	int i;
1038155a6bd6SMark Brown 
1039155a6bd6SMark Brown 	config = raw_regmap_config;
1040155a6bd6SMark Brown 
1041155a6bd6SMark Brown 	map = gen_raw_regmap(&config, t, &data);
1042155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1043155a6bd6SMark Brown 	if (IS_ERR(map))
1044155a6bd6SMark Brown 		return;
1045155a6bd6SMark Brown 
1046155a6bd6SMark Brown 	val_len = sizeof(*rval) * (config.max_register + 1);
1047155a6bd6SMark Brown 	rval = kmalloc(val_len, GFP_KERNEL);
1048155a6bd6SMark Brown 	KUNIT_ASSERT_TRUE(test, rval != NULL);
1049155a6bd6SMark Brown 	if (!rval)
1050155a6bd6SMark Brown 		return;
1051155a6bd6SMark Brown 
1052155a6bd6SMark Brown 	/* Check that we can read the defaults via the API */
1053155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_raw_read(map, 0, rval, val_len));
1054155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1055155a6bd6SMark Brown 		def = config.reg_defaults[i].def;
1056155a6bd6SMark Brown 		if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1057155a6bd6SMark Brown 			KUNIT_EXPECT_EQ(test, def, be16_to_cpu(rval[i]));
1058155a6bd6SMark Brown 		} else {
1059155a6bd6SMark Brown 			KUNIT_EXPECT_EQ(test, def, le16_to_cpu(rval[i]));
1060155a6bd6SMark Brown 		}
1061155a6bd6SMark Brown 	}
1062155a6bd6SMark Brown 
1063155a6bd6SMark Brown 	kfree(rval);
1064155a6bd6SMark Brown 	regmap_exit(map);
1065155a6bd6SMark Brown }
1066155a6bd6SMark Brown 
raw_write_read_single(struct kunit * test)1067155a6bd6SMark Brown static void raw_write_read_single(struct kunit *test)
1068155a6bd6SMark Brown {
1069155a6bd6SMark Brown 	struct raw_test_types *t = (struct raw_test_types *)test->param_value;
1070155a6bd6SMark Brown 	struct regmap *map;
1071155a6bd6SMark Brown 	struct regmap_config config;
1072155a6bd6SMark Brown 	struct regmap_ram_data *data;
1073155a6bd6SMark Brown 	u16 val;
1074155a6bd6SMark Brown 	unsigned int rval;
1075155a6bd6SMark Brown 
1076155a6bd6SMark Brown 	config = raw_regmap_config;
1077155a6bd6SMark Brown 
1078155a6bd6SMark Brown 	map = gen_raw_regmap(&config, t, &data);
1079155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1080155a6bd6SMark Brown 	if (IS_ERR(map))
1081155a6bd6SMark Brown 		return;
1082155a6bd6SMark Brown 
1083155a6bd6SMark Brown 	get_random_bytes(&val, sizeof(val));
1084155a6bd6SMark Brown 
1085155a6bd6SMark Brown 	/* If we write a value to a register we can read it back */
1086155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
1087155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
1088155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, val, rval);
1089155a6bd6SMark Brown 
1090155a6bd6SMark Brown 	regmap_exit(map);
1091155a6bd6SMark Brown }
1092155a6bd6SMark Brown 
raw_write(struct kunit * test)1093155a6bd6SMark Brown static void raw_write(struct kunit *test)
1094155a6bd6SMark Brown {
1095155a6bd6SMark Brown 	struct raw_test_types *t = (struct raw_test_types *)test->param_value;
1096155a6bd6SMark Brown 	struct regmap *map;
1097155a6bd6SMark Brown 	struct regmap_config config;
1098155a6bd6SMark Brown 	struct regmap_ram_data *data;
1099155a6bd6SMark Brown 	u16 *hw_buf;
1100155a6bd6SMark Brown 	u16 val[2];
1101155a6bd6SMark Brown 	unsigned int rval;
1102155a6bd6SMark Brown 	int i;
1103155a6bd6SMark Brown 
1104155a6bd6SMark Brown 	config = raw_regmap_config;
1105155a6bd6SMark Brown 
1106155a6bd6SMark Brown 	map = gen_raw_regmap(&config, t, &data);
1107155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1108155a6bd6SMark Brown 	if (IS_ERR(map))
1109155a6bd6SMark Brown 		return;
1110155a6bd6SMark Brown 
1111155a6bd6SMark Brown 	hw_buf = (u16 *)data->vals;
1112155a6bd6SMark Brown 
1113155a6bd6SMark Brown 	get_random_bytes(&val, sizeof(val));
1114155a6bd6SMark Brown 
1115155a6bd6SMark Brown 	/* Do a raw write */
1116155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
1117155a6bd6SMark Brown 
1118155a6bd6SMark Brown 	/* We should read back the new values, and defaults for the rest */
1119155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1120155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
1121155a6bd6SMark Brown 
1122155a6bd6SMark Brown 		switch (i) {
1123155a6bd6SMark Brown 		case 2:
1124155a6bd6SMark Brown 		case 3:
1125155a6bd6SMark Brown 			if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1126155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1127155a6bd6SMark Brown 						be16_to_cpu(val[i % 2]));
1128155a6bd6SMark Brown 			} else {
1129155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1130155a6bd6SMark Brown 						le16_to_cpu(val[i % 2]));
1131155a6bd6SMark Brown 			}
1132155a6bd6SMark Brown 			break;
1133155a6bd6SMark Brown 		default:
1134155a6bd6SMark Brown 			KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1135155a6bd6SMark Brown 			break;
1136155a6bd6SMark Brown 		}
1137155a6bd6SMark Brown 	}
1138155a6bd6SMark Brown 
1139155a6bd6SMark Brown 	/* The values should appear in the "hardware" */
1140155a6bd6SMark Brown 	KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
1141155a6bd6SMark Brown 
1142155a6bd6SMark Brown 	regmap_exit(map);
1143155a6bd6SMark Brown }
1144155a6bd6SMark Brown 
raw_sync(struct kunit * test)1145155a6bd6SMark Brown static void raw_sync(struct kunit *test)
1146155a6bd6SMark Brown {
1147155a6bd6SMark Brown 	struct raw_test_types *t = (struct raw_test_types *)test->param_value;
1148155a6bd6SMark Brown 	struct regmap *map;
1149155a6bd6SMark Brown 	struct regmap_config config;
1150155a6bd6SMark Brown 	struct regmap_ram_data *data;
1151*d1b6521cSMark Brown 	u16 val[3];
1152155a6bd6SMark Brown 	u16 *hw_buf;
1153155a6bd6SMark Brown 	unsigned int rval;
1154155a6bd6SMark Brown 	int i;
1155155a6bd6SMark Brown 
1156155a6bd6SMark Brown 	config = raw_regmap_config;
1157155a6bd6SMark Brown 
1158155a6bd6SMark Brown 	map = gen_raw_regmap(&config, t, &data);
1159155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1160155a6bd6SMark Brown 	if (IS_ERR(map))
1161155a6bd6SMark Brown 		return;
1162155a6bd6SMark Brown 
1163155a6bd6SMark Brown 	hw_buf = (u16 *)data->vals;
1164155a6bd6SMark Brown 
1165*d1b6521cSMark Brown 	get_changed_bytes(&hw_buf[2], &val[0], sizeof(val));
1166155a6bd6SMark Brown 
1167155a6bd6SMark Brown 	/* Do a regular write and a raw write in cache only mode */
1168155a6bd6SMark Brown 	regcache_cache_only(map, true);
1169*d1b6521cSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val,
1170*d1b6521cSMark Brown 						  sizeof(u16) * 2));
1171*d1b6521cSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 4, val[2]));
1172155a6bd6SMark Brown 
1173155a6bd6SMark Brown 	/* We should read back the new values, and defaults for the rest */
1174155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1175155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
1176155a6bd6SMark Brown 
1177155a6bd6SMark Brown 		switch (i) {
1178155a6bd6SMark Brown 		case 2:
1179155a6bd6SMark Brown 		case 3:
1180155a6bd6SMark Brown 			if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1181155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1182*d1b6521cSMark Brown 						be16_to_cpu(val[i - 2]));
1183155a6bd6SMark Brown 			} else {
1184155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1185*d1b6521cSMark Brown 						le16_to_cpu(val[i - 2]));
1186155a6bd6SMark Brown 			}
1187155a6bd6SMark Brown 			break;
1188*d1b6521cSMark Brown 		case 4:
1189*d1b6521cSMark Brown 			KUNIT_EXPECT_EQ(test, rval, val[i - 2]);
1190*d1b6521cSMark Brown 			break;
1191155a6bd6SMark Brown 		default:
1192155a6bd6SMark Brown 			KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1193155a6bd6SMark Brown 			break;
1194155a6bd6SMark Brown 		}
1195155a6bd6SMark Brown 	}
1196155a6bd6SMark Brown 
1197*d1b6521cSMark Brown 	/*
1198*d1b6521cSMark Brown 	 * The value written via _write() was translated by the core,
1199*d1b6521cSMark Brown 	 * translate the original copy for comparison purposes.
1200*d1b6521cSMark Brown 	 */
1201*d1b6521cSMark Brown 	if (config.val_format_endian == REGMAP_ENDIAN_BIG)
1202*d1b6521cSMark Brown 		val[2] = cpu_to_be16(val[2]);
1203*d1b6521cSMark Brown 	else
1204*d1b6521cSMark Brown 		val[2] = cpu_to_le16(val[2]);
1205*d1b6521cSMark Brown 
1206155a6bd6SMark Brown 	/* The values should not appear in the "hardware" */
1207*d1b6521cSMark Brown 	KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], &val[0], sizeof(val));
1208155a6bd6SMark Brown 
1209155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++)
1210155a6bd6SMark Brown 		data->written[i] = false;
1211155a6bd6SMark Brown 
1212155a6bd6SMark Brown 	/* Do the sync */
1213155a6bd6SMark Brown 	regcache_cache_only(map, false);
1214155a6bd6SMark Brown 	regcache_mark_dirty(map);
1215155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
1216155a6bd6SMark Brown 
1217155a6bd6SMark Brown 	/* The values should now appear in the "hardware" */
1218*d1b6521cSMark Brown 	KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], &val[0], sizeof(val));
1219155a6bd6SMark Brown 
1220155a6bd6SMark Brown 	regmap_exit(map);
1221155a6bd6SMark Brown }
1222155a6bd6SMark Brown 
12232238959bSMark Brown static struct kunit_case regmap_test_cases[] = {
12242238959bSMark Brown 	KUNIT_CASE_PARAM(basic_read_write, regcache_types_gen_params),
12252238959bSMark Brown 	KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
12262238959bSMark Brown 	KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params),
122718003306SMark Brown 	KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params),
1228a07bff40SMark Brown 	KUNIT_CASE_PARAM(read_writeonly, regcache_types_gen_params),
12292238959bSMark Brown 	KUNIT_CASE_PARAM(reg_defaults, regcache_types_gen_params),
12302238959bSMark Brown 	KUNIT_CASE_PARAM(reg_defaults_read_dev, regcache_types_gen_params),
12312238959bSMark Brown 	KUNIT_CASE_PARAM(register_patch, regcache_types_gen_params),
12322238959bSMark Brown 	KUNIT_CASE_PARAM(stride, regcache_types_gen_params),
12332238959bSMark Brown 	KUNIT_CASE_PARAM(basic_ranges, regcache_types_gen_params),
12342238959bSMark Brown 	KUNIT_CASE_PARAM(stress_insert, regcache_types_gen_params),
12352238959bSMark Brown 	KUNIT_CASE_PARAM(cache_bypass, real_cache_types_gen_params),
12362238959bSMark Brown 	KUNIT_CASE_PARAM(cache_sync, real_cache_types_gen_params),
12372238959bSMark Brown 	KUNIT_CASE_PARAM(cache_sync_defaults, real_cache_types_gen_params),
1238357a1ebdSMark Brown 	KUNIT_CASE_PARAM(cache_sync_readonly, real_cache_types_gen_params),
12392238959bSMark Brown 	KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
12402238959bSMark Brown 	KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
1241d881ee5aSMark Brown 	KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
1242155a6bd6SMark Brown 
1243155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
1244155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
1245155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_write_read_single, raw_test_types_gen_params),
1246155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params),
1247155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params),
12482238959bSMark Brown 	{}
12492238959bSMark Brown };
12502238959bSMark Brown 
12512238959bSMark Brown static struct kunit_suite regmap_test_suite = {
12522238959bSMark Brown 	.name = "regmap",
12532238959bSMark Brown 	.test_cases = regmap_test_cases,
12542238959bSMark Brown };
12552238959bSMark Brown kunit_test_suite(regmap_test_suite);
12562238959bSMark Brown 
12572238959bSMark Brown MODULE_LICENSE("GPL v2");
1258