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