Skip to content

Commit ecfb8ce

Browse files
committed
regmap: Provide basic test coverage for raw I/O
Merge series from Mark Brown <broonie@kernel.org>: Our existing coverage only deals with buses that provide single register read and write operations, extend it to cover raw buses using a similar approach with a RAM backed register map that the tests can inspect to check operations. This coverage could be more complete but provides a good start.
2 parents d32758a + 155a6bd commit ecfb8ce

4 files changed

Lines changed: 469 additions & 1 deletion

File tree

drivers/base/regmap/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
88
obj-$(CONFIG_REGMAP_KUNIT) += regmap-kunit.o
99
obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o
1010
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
11-
obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o
11+
obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o regmap-raw-ram.o
1212
obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o
1313
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
1414
obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o

drivers/base/regmap/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ struct regmap_ram_data {
314314
unsigned int *vals; /* Allocatd by caller */
315315
bool *read;
316316
bool *written;
317+
enum regmap_endian reg_endian;
317318
};
318319

319320
/*
@@ -328,5 +329,12 @@ struct regmap *__regmap_init_ram(const struct regmap_config *config,
328329
#define regmap_init_ram(config, data) \
329330
__regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data)
330331

332+
struct regmap *__regmap_init_raw_ram(const struct regmap_config *config,
333+
struct regmap_ram_data *data,
334+
struct lock_class_key *lock_key,
335+
const char *lock_name);
336+
337+
#define regmap_init_raw_ram(config, data) \
338+
__regmap_lockdep_wrapper(__regmap_init_raw_ram, #config, config, data)
331339

332340
#endif

drivers/base/regmap/regmap-kunit.c

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,327 @@ static void cache_drop(struct kunit *test)
712712
regmap_exit(map);
713713
}
714714

715+
struct raw_test_types {
716+
const char *name;
717+
718+
enum regcache_type cache_type;
719+
enum regmap_endian val_endian;
720+
};
721+
722+
static void raw_to_desc(const struct raw_test_types *t, char *desc)
723+
{
724+
strcpy(desc, t->name);
725+
}
726+
727+
static const struct raw_test_types raw_types_list[] = {
728+
{ "none-little", REGCACHE_NONE, REGMAP_ENDIAN_LITTLE },
729+
{ "none-big", REGCACHE_NONE, REGMAP_ENDIAN_BIG },
730+
{ "flat-little", REGCACHE_FLAT, REGMAP_ENDIAN_LITTLE },
731+
{ "flat-big", REGCACHE_FLAT, REGMAP_ENDIAN_BIG },
732+
{ "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE },
733+
{ "rbtree-big", REGCACHE_RBTREE, REGMAP_ENDIAN_BIG },
734+
{ "maple-little", REGCACHE_MAPLE, REGMAP_ENDIAN_LITTLE },
735+
{ "maple-big", REGCACHE_MAPLE, REGMAP_ENDIAN_BIG },
736+
};
737+
738+
KUNIT_ARRAY_PARAM(raw_test_types, raw_types_list, raw_to_desc);
739+
740+
static const struct raw_test_types raw_cache_types_list[] = {
741+
{ "flat-little", REGCACHE_FLAT, REGMAP_ENDIAN_LITTLE },
742+
{ "flat-big", REGCACHE_FLAT, REGMAP_ENDIAN_BIG },
743+
{ "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE },
744+
{ "rbtree-big", REGCACHE_RBTREE, REGMAP_ENDIAN_BIG },
745+
{ "maple-little", REGCACHE_MAPLE, REGMAP_ENDIAN_LITTLE },
746+
{ "maple-big", REGCACHE_MAPLE, REGMAP_ENDIAN_BIG },
747+
};
748+
749+
KUNIT_ARRAY_PARAM(raw_test_cache_types, raw_cache_types_list, raw_to_desc);
750+
751+
static const struct regmap_config raw_regmap_config = {
752+
.max_register = BLOCK_TEST_SIZE,
753+
754+
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
755+
.reg_bits = 16,
756+
.val_bits = 16,
757+
};
758+
759+
static struct regmap *gen_raw_regmap(struct regmap_config *config,
760+
struct raw_test_types *test_type,
761+
struct regmap_ram_data **data)
762+
{
763+
u16 *buf;
764+
struct regmap *ret;
765+
size_t size = (config->max_register + 1) * config->reg_bits / 8;
766+
int i;
767+
struct reg_default *defaults;
768+
769+
config->cache_type = test_type->cache_type;
770+
config->val_format_endian = test_type->val_endian;
771+
772+
buf = kmalloc(size, GFP_KERNEL);
773+
if (!buf)
774+
return ERR_PTR(-ENOMEM);
775+
776+
get_random_bytes(buf, size);
777+
778+
*data = kzalloc(sizeof(**data), GFP_KERNEL);
779+
if (!(*data))
780+
return ERR_PTR(-ENOMEM);
781+
(*data)->vals = (void *)buf;
782+
783+
config->num_reg_defaults = config->max_register + 1;
784+
defaults = kcalloc(config->num_reg_defaults,
785+
sizeof(struct reg_default),
786+
GFP_KERNEL);
787+
if (!defaults)
788+
return ERR_PTR(-ENOMEM);
789+
config->reg_defaults = defaults;
790+
791+
for (i = 0; i < config->num_reg_defaults; i++) {
792+
defaults[i].reg = i;
793+
switch (test_type->val_endian) {
794+
case REGMAP_ENDIAN_LITTLE:
795+
defaults[i].def = le16_to_cpu(buf[i]);
796+
break;
797+
case REGMAP_ENDIAN_BIG:
798+
defaults[i].def = be16_to_cpu(buf[i]);
799+
break;
800+
default:
801+
return ERR_PTR(-EINVAL);
802+
}
803+
}
804+
805+
/*
806+
* We use the defaults in the tests but they don't make sense
807+
* to the core if there's no cache.
808+
*/
809+
if (config->cache_type == REGCACHE_NONE)
810+
config->num_reg_defaults = 0;
811+
812+
ret = regmap_init_raw_ram(config, *data);
813+
if (IS_ERR(ret)) {
814+
kfree(buf);
815+
kfree(*data);
816+
}
817+
818+
return ret;
819+
}
820+
821+
static void raw_read_defaults_single(struct kunit *test)
822+
{
823+
struct raw_test_types *t = (struct raw_test_types *)test->param_value;
824+
struct regmap *map;
825+
struct regmap_config config;
826+
struct regmap_ram_data *data;
827+
unsigned int rval;
828+
int i;
829+
830+
config = raw_regmap_config;
831+
832+
map = gen_raw_regmap(&config, t, &data);
833+
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
834+
if (IS_ERR(map))
835+
return;
836+
837+
/* Check that we can read the defaults via the API */
838+
for (i = 0; i < config.max_register + 1; i++) {
839+
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
840+
KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
841+
}
842+
843+
regmap_exit(map);
844+
}
845+
846+
static void raw_read_defaults(struct kunit *test)
847+
{
848+
struct raw_test_types *t = (struct raw_test_types *)test->param_value;
849+
struct regmap *map;
850+
struct regmap_config config;
851+
struct regmap_ram_data *data;
852+
u16 *rval;
853+
u16 def;
854+
size_t val_len;
855+
int i;
856+
857+
config = raw_regmap_config;
858+
859+
map = gen_raw_regmap(&config, t, &data);
860+
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
861+
if (IS_ERR(map))
862+
return;
863+
864+
val_len = sizeof(*rval) * (config.max_register + 1);
865+
rval = kmalloc(val_len, GFP_KERNEL);
866+
KUNIT_ASSERT_TRUE(test, rval != NULL);
867+
if (!rval)
868+
return;
869+
870+
/* Check that we can read the defaults via the API */
871+
KUNIT_EXPECT_EQ(test, 0, regmap_raw_read(map, 0, rval, val_len));
872+
for (i = 0; i < config.max_register + 1; i++) {
873+
def = config.reg_defaults[i].def;
874+
if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
875+
KUNIT_EXPECT_EQ(test, def, be16_to_cpu(rval[i]));
876+
} else {
877+
KUNIT_EXPECT_EQ(test, def, le16_to_cpu(rval[i]));
878+
}
879+
}
880+
881+
kfree(rval);
882+
regmap_exit(map);
883+
}
884+
885+
static void raw_write_read_single(struct kunit *test)
886+
{
887+
struct raw_test_types *t = (struct raw_test_types *)test->param_value;
888+
struct regmap *map;
889+
struct regmap_config config;
890+
struct regmap_ram_data *data;
891+
u16 val;
892+
unsigned int rval;
893+
894+
config = raw_regmap_config;
895+
896+
map = gen_raw_regmap(&config, t, &data);
897+
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
898+
if (IS_ERR(map))
899+
return;
900+
901+
get_random_bytes(&val, sizeof(val));
902+
903+
/* If we write a value to a register we can read it back */
904+
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
905+
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
906+
KUNIT_EXPECT_EQ(test, val, rval);
907+
908+
regmap_exit(map);
909+
}
910+
911+
static void raw_write(struct kunit *test)
912+
{
913+
struct raw_test_types *t = (struct raw_test_types *)test->param_value;
914+
struct regmap *map;
915+
struct regmap_config config;
916+
struct regmap_ram_data *data;
917+
u16 *hw_buf;
918+
u16 val[2];
919+
unsigned int rval;
920+
int i;
921+
922+
config = raw_regmap_config;
923+
924+
map = gen_raw_regmap(&config, t, &data);
925+
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
926+
if (IS_ERR(map))
927+
return;
928+
929+
hw_buf = (u16 *)data->vals;
930+
931+
get_random_bytes(&val, sizeof(val));
932+
933+
/* Do a raw write */
934+
KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
935+
936+
/* We should read back the new values, and defaults for the rest */
937+
for (i = 0; i < config.max_register + 1; i++) {
938+
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
939+
940+
switch (i) {
941+
case 2:
942+
case 3:
943+
if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
944+
KUNIT_EXPECT_EQ(test, rval,
945+
be16_to_cpu(val[i % 2]));
946+
} else {
947+
KUNIT_EXPECT_EQ(test, rval,
948+
le16_to_cpu(val[i % 2]));
949+
}
950+
break;
951+
default:
952+
KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
953+
break;
954+
}
955+
}
956+
957+
/* The values should appear in the "hardware" */
958+
KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
959+
960+
regmap_exit(map);
961+
}
962+
963+
static void raw_sync(struct kunit *test)
964+
{
965+
struct raw_test_types *t = (struct raw_test_types *)test->param_value;
966+
struct regmap *map;
967+
struct regmap_config config;
968+
struct regmap_ram_data *data;
969+
u16 val[2];
970+
u16 *hw_buf;
971+
unsigned int rval;
972+
int i;
973+
974+
config = raw_regmap_config;
975+
976+
map = gen_raw_regmap(&config, t, &data);
977+
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
978+
if (IS_ERR(map))
979+
return;
980+
981+
hw_buf = (u16 *)data->vals;
982+
983+
get_random_bytes(&val, sizeof(val));
984+
985+
/* Do a regular write and a raw write in cache only mode */
986+
regcache_cache_only(map, true);
987+
KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
988+
if (config.val_format_endian == REGMAP_ENDIAN_BIG)
989+
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6,
990+
be16_to_cpu(val[0])));
991+
else
992+
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6,
993+
le16_to_cpu(val[0])));
994+
995+
/* We should read back the new values, and defaults for the rest */
996+
for (i = 0; i < config.max_register + 1; i++) {
997+
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
998+
999+
switch (i) {
1000+
case 2:
1001+
case 3:
1002+
case 6:
1003+
if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1004+
KUNIT_EXPECT_EQ(test, rval,
1005+
be16_to_cpu(val[i % 2]));
1006+
} else {
1007+
KUNIT_EXPECT_EQ(test, rval,
1008+
le16_to_cpu(val[i % 2]));
1009+
}
1010+
break;
1011+
default:
1012+
KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1013+
break;
1014+
}
1015+
}
1016+
1017+
/* The values should not appear in the "hardware" */
1018+
KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], val, sizeof(val));
1019+
KUNIT_EXPECT_MEMNEQ(test, &hw_buf[6], val, sizeof(u16));
1020+
1021+
for (i = 0; i < config.max_register + 1; i++)
1022+
data->written[i] = false;
1023+
1024+
/* Do the sync */
1025+
regcache_cache_only(map, false);
1026+
regcache_mark_dirty(map);
1027+
KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
1028+
1029+
/* The values should now appear in the "hardware" */
1030+
KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
1031+
KUNIT_EXPECT_MEMEQ(test, &hw_buf[6], val, sizeof(u16));
1032+
1033+
regmap_exit(map);
1034+
}
1035+
7151036
static struct kunit_case regmap_test_cases[] = {
7161037
KUNIT_CASE_PARAM(basic_read_write, regcache_types_gen_params),
7171038
KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
@@ -727,6 +1048,12 @@ static struct kunit_case regmap_test_cases[] = {
7271048
KUNIT_CASE_PARAM(cache_sync_defaults, real_cache_types_gen_params),
7281049
KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
7291050
KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
1051+
1052+
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
1053+
KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
1054+
KUNIT_CASE_PARAM(raw_write_read_single, raw_test_types_gen_params),
1055+
KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params),
1056+
KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params),
7301057
{}
7311058
};
7321059

0 commit comments

Comments
 (0)