File Index
Files and directories
Sign in
FILE

cs_dsp_test_control_cache.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/cirrus/test/cs_dsp_test_control_cache.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2//
   3// KUnit tests for cs_dsp.
   4//
   5// Copyright (C) 2024 Cirrus Logic, Inc. and
   6//                    Cirrus Logic International Semiconductor Ltd.
   7
   8#include <kunit/device.h>
   9#include <kunit/resource.h>
  10#include <kunit/test.h>
  11#include <linux/build_bug.h>
  12#include <linux/firmware/cirrus/cs_dsp.h>
  13#include <linux/firmware/cirrus/cs_dsp_test_utils.h>
  14#include <linux/firmware/cirrus/wmfw.h>
  15#include <linux/list.h>
  16#include <linux/random.h>
  17#include <linux/regmap.h>
  18
  19KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
  20KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_stop_wrapper, cs_dsp_stop, struct cs_dsp *);
  21KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
  22
  23struct cs_dsp_test_local {
  24	struct cs_dsp_mock_xm_header *xm_header;
  25	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
  26	int wmfw_version;
  27};
  28
  29struct cs_dsp_ctl_cache_test_param {
  30	int mem_type;
  31	int alg_id;
  32	unsigned int offs_words;
  33	unsigned int len_bytes;
  34	u16 ctl_type;
  35	u16 flags;
  36};
  37
  38static const struct cs_dsp_mock_alg_def cs_dsp_ctl_cache_test_algs[] = {
  39	{
  40		.id = 0xfafa,
  41		.ver = 0x100000,
  42		.xm_base_words = 60,
  43		.xm_size_words = 1000,
  44		.ym_base_words = 0,
  45		.ym_size_words = 1000,
  46		.zm_base_words = 0,
  47		.zm_size_words = 1000,
  48	},
  49	{
  50		.id = 0xb,
  51		.ver = 0x100001,
  52		.xm_base_words = 1060,
  53		.xm_size_words = 1000,
  54		.ym_base_words = 1000,
  55		.ym_size_words = 1000,
  56		.zm_base_words = 1000,
  57		.zm_size_words = 1000,
  58	},
  59	{
  60		.id = 0x9f1234,
  61		.ver = 0x100500,
  62		.xm_base_words = 2060,
  63		.xm_size_words = 32,
  64		.ym_base_words = 2000,
  65		.ym_size_words = 32,
  66		.zm_base_words = 2000,
  67		.zm_size_words = 32,
  68	},
  69	{
  70		.id = 0xff00ff,
  71		.ver = 0x300113,
  72		.xm_base_words = 2100,
  73		.xm_size_words = 32,
  74		.ym_base_words = 2032,
  75		.ym_size_words = 32,
  76		.zm_base_words = 2032,
  77		.zm_size_words = 32,
  78	},
  79};
  80
  81static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
  82	.shortname = "Dummy Coeff",
  83	.type = WMFW_CTL_TYPE_BYTES,
  84	.mem_type = WMFW_ADSP2_YM,
  85	.flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
  86	.length_bytes = 4,
  87};
  88
  89static const char * const cs_dsp_ctl_cache_test_fw_names[] = {
  90	"misc", "mbc/vss", "haps",
  91};
  92
  93static int _find_alg_entry(struct kunit *test, unsigned int alg_id)
  94{
  95	int i;
  96
  97	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_cache_test_algs); ++i) {
  98		if (cs_dsp_ctl_cache_test_algs[i].id == alg_id)
  99			break;
 100	}
 101
 102	KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
 103
 104	return i;
 105}
 106
 107static int _get_alg_mem_base_words(struct kunit *test, int alg_index, int mem_type)
 108{
 109	switch (mem_type) {
 110	case WMFW_ADSP2_XM:
 111		return cs_dsp_ctl_cache_test_algs[alg_index].xm_base_words;
 112	case WMFW_ADSP2_YM:
 113		return cs_dsp_ctl_cache_test_algs[alg_index].ym_base_words;
 114	case WMFW_ADSP2_ZM:
 115		return cs_dsp_ctl_cache_test_algs[alg_index].zm_base_words;
 116	default:
 117		KUNIT_FAIL(test, "Bug in test: illegal memory type %d\n", mem_type);
 118		return 0;
 119	}
 120}
 121
 122static struct cs_dsp_mock_wmfw_builder *_create_dummy_wmfw(struct kunit *test)
 123{
 124	struct cs_dsp_test *priv = test->priv;
 125	struct cs_dsp_test_local *local = priv->local;
 126	struct cs_dsp_mock_wmfw_builder *builder;
 127
 128	builder = cs_dsp_mock_wmfw_init(priv, local->wmfw_version);
 129	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder);
 130
 131	/* Init an XM header */
 132	cs_dsp_mock_wmfw_add_data_block(builder,
 133					WMFW_ADSP2_XM, 0,
 134					local->xm_header->blob_data,
 135					local->xm_header->blob_size_bytes);
 136
 137	return builder;
 138}
 139
 140/*
 141 * Memory allocated for control cache must be large enough.
 142 * This creates multiple controls of different sizes so only works on
 143 * wmfw V2 and later.
 144 */
 145static void cs_dsp_ctl_v2_cache_alloc(struct kunit *test)
 146{
 147	struct cs_dsp_test *priv = test->priv;
 148	struct cs_dsp_test_local *local = priv->local;
 149	struct cs_dsp *dsp = priv->dsp;
 150	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 151	unsigned int reg, alg_base_words, alg_size_bytes;
 152	struct cs_dsp_coeff_ctl *ctl;
 153	struct firmware *wmfw;
 154	char ctl_name[4];
 155	u32 *reg_vals;
 156	int num_ctls;
 157
 158	/* Create some DSP data to initialize the control cache */
 159	alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_YM);
 160	alg_size_bytes = cs_dsp_ctl_cache_test_algs[0].ym_size_words *
 161			 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 162	reg_vals = kunit_kzalloc(test, alg_size_bytes, GFP_KERNEL);
 163	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 164	reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
 165	reg += alg_base_words *	cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 166	regmap_raw_write(dsp->regmap, reg, reg_vals, alg_size_bytes);
 167
 168	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 169					      cs_dsp_ctl_cache_test_algs[0].id,
 170					      "dummyalg", NULL);
 171
 172	/* Create controls of different sizes */
 173	def.mem_type = WMFW_ADSP2_YM;
 174	def.shortname = ctl_name;
 175	num_ctls = 0;
 176	for (def.length_bytes = 4; def.length_bytes <= 64; def.length_bytes += 4) {
 177		snprintf(ctl_name, ARRAY_SIZE(ctl_name), "%x", def.length_bytes);
 178		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 179		num_ctls++;
 180		def.offset_dsp_words += def.length_bytes / sizeof(u32);
 181	}
 182	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 183
 184	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 185	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 186
 187	KUNIT_EXPECT_EQ(test, list_count_nodes(&dsp->ctl_list), num_ctls);
 188
 189	/* Check that the block allocated for the cache is large enough */
 190	list_for_each_entry(ctl, &dsp->ctl_list, list)
 191		KUNIT_EXPECT_GE(test, ksize(ctl->cache), ctl->len);
 192}
 193
 194/*
 195 * Content of registers backing a control should be read into the
 196 * control cache when the firmware is downloaded.
 197 */
 198static void cs_dsp_ctl_cache_init(struct kunit *test)
 199{
 200	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
 201	struct cs_dsp_test *priv = test->priv;
 202	struct cs_dsp_test_local *local = priv->local;
 203	struct cs_dsp *dsp = priv->dsp;
 204	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 205	int alg_idx = _find_alg_entry(test, param->alg_id);
 206	unsigned int reg, alg_base_words;
 207	struct cs_dsp_coeff_ctl *ctl;
 208	struct firmware *wmfw;
 209	u32 *reg_vals, *readback;
 210
 211	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 212	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 213
 214	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 215	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 216
 217	/* Create some DSP data to be read into the control cache */
 218	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 219	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 220	reg += (alg_base_words + param->offs_words) *
 221		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 222	get_random_bytes(reg_vals, param->len_bytes);
 223	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 224
 225	/* Create control pointing to this data */
 226	def.flags = param->flags;
 227	def.mem_type = param->mem_type;
 228	def.offset_dsp_words = param->offs_words;
 229	def.length_bytes = param->len_bytes;
 230
 231	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 232					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
 233					      "dummyalg", NULL);
 234	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 235	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 236
 237	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 238	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 239
 240	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 241	KUNIT_ASSERT_NOT_NULL(test, ctl);
 242
 243	/*
 244	 * The data should have been populated into the control cache
 245	 * so should be readable through the control.
 246	 */
 247	KUNIT_EXPECT_EQ(test,
 248			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
 249			0);
 250	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
 251}
 252
 253/*
 254 * For a non-volatile write-only control the cache should be zero-filled
 255 * when the firmware is downloaded.
 256 */
 257static void cs_dsp_ctl_cache_init_write_only(struct kunit *test)
 258{
 259	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
 260	struct cs_dsp_test *priv = test->priv;
 261	struct cs_dsp_test_local *local = priv->local;
 262	struct cs_dsp *dsp = priv->dsp;
 263	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 264	int alg_idx = _find_alg_entry(test, param->alg_id);
 265	struct cs_dsp_coeff_ctl *ctl;
 266	struct firmware *wmfw;
 267	u32 *readback, *zeros;
 268
 269	zeros = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 270	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, zeros);
 271
 272	readback = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 273	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 274
 275	/* Create a non-volatile write-only control */
 276	def.flags = param->flags & ~WMFW_CTL_FLAG_VOLATILE;
 277	def.mem_type = param->mem_type;
 278	def.offset_dsp_words = param->offs_words;
 279	def.length_bytes = param->len_bytes;
 280
 281	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 282					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
 283					      "dummyalg", NULL);
 284	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 285	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 286
 287	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 288	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 289
 290	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 291	KUNIT_ASSERT_NOT_NULL(test, ctl);
 292
 293	/*
 294	 * The control cache should have been zero-filled so should be
 295	 * readable through the control.
 296	 */
 297	get_random_bytes(readback, param->len_bytes);
 298	KUNIT_EXPECT_EQ(test,
 299			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
 300			0);
 301	KUNIT_EXPECT_MEMEQ(test, readback, zeros, param->len_bytes);
 302}
 303
 304/*
 305 * Multiple different firmware with identical controls.
 306 * This is legal because different firmwares could contain the same
 307 * algorithm.
 308 * The control cache should be initialized only with the data from
 309 * the firmware containing it.
 310 */
 311static void cs_dsp_ctl_cache_init_multiple_fw_same_controls(struct kunit *test)
 312{
 313	struct cs_dsp_test *priv = test->priv;
 314	struct cs_dsp *dsp = priv->dsp;
 315	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 316	struct cs_dsp_mock_wmfw_builder *builder[3];
 317	unsigned int reg, alg_base_words;
 318	struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
 319	struct firmware *wmfw;
 320	u32 *reg_vals[3], *readback;
 321	int i;
 322
 323	static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(builder));
 324	static_assert(ARRAY_SIZE(reg_vals) == ARRAY_SIZE(builder));
 325	static_assert(ARRAY_SIZE(cs_dsp_ctl_cache_test_fw_names) >= ARRAY_SIZE(builder));
 326
 327	/* Create an identical control in each firmware but with different alg id */
 328	for (i = 0; i < ARRAY_SIZE(builder); i++) {
 329		builder[i] = _create_dummy_wmfw(test);
 330		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder[i]);
 331
 332		cs_dsp_mock_wmfw_start_alg_info_block(builder[i],
 333						      cs_dsp_ctl_cache_test_algs[0].id,
 334						      "dummyalg", NULL);
 335		cs_dsp_mock_wmfw_add_coeff_desc(builder[i], &def);
 336		cs_dsp_mock_wmfw_end_alg_info_block(builder[i]);
 337	}
 338
 339	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 340		reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 341		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
 342	}
 343
 344	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 345	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 346
 347	/*
 348	 * For each firmware create random content in the register backing
 349	 * the control. Then download, start, stop and power-down.
 350	 */
 351	for (i = 0; i < ARRAY_SIZE(builder); i++) {
 352		alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type);
 353		reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
 354		reg += (alg_base_words + def.offset_dsp_words) *
 355			cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 356
 357		get_random_bytes(reg_vals[i], def.length_bytes);
 358		regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes);
 359		wmfw = cs_dsp_mock_wmfw_get_firmware(builder[i]);
 360		KUNIT_ASSERT_EQ(test,
 361				cs_dsp_power_up(dsp, wmfw,
 362						cs_dsp_ctl_cache_test_fw_names[i],
 363						NULL, NULL,
 364						cs_dsp_ctl_cache_test_fw_names[i]),
 365				0);
 366		KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 367		cs_dsp_stop(dsp);
 368		cs_dsp_power_down(dsp);
 369	}
 370
 371	/* There should now be 3 controls */
 372	KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
 373
 374	/*
 375	 * There's no requirement for the control list to be in any
 376	 * particular order, so don't assume the order.
 377	 */
 378	for (i = 0; i < ARRAY_SIZE(ctl); i++)
 379		ctl[i] = NULL;
 380
 381	list_for_each_entry(walkctl, &dsp->ctl_list, list) {
 382		if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[0]) == 0)
 383			ctl[0] = walkctl;
 384		else if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[1]) == 0)
 385			ctl[1] = walkctl;
 386		else if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[2]) == 0)
 387			ctl[2] = walkctl;
 388	}
 389
 390	KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
 391	KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
 392	KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
 393
 394	/*
 395	 * The data should have been populated into the control cache
 396	 * so should be readable through the control.
 397	 */
 398	KUNIT_EXPECT_EQ(test,
 399			cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
 400			0);
 401	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
 402
 403	KUNIT_EXPECT_EQ(test,
 404			cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
 405			0);
 406	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
 407
 408	KUNIT_EXPECT_EQ(test,
 409			cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, def.length_bytes),
 410			0);
 411	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
 412}
 413
 414/*
 415 * Multiple different firmware with controls identical except for alg id.
 416 * This is legal because the controls are qualified by algorithm id.
 417 * The control cache should be initialized only with the data from
 418 * the firmware containing it.
 419 */
 420static void cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls(struct kunit *test)
 421{
 422	struct cs_dsp_test *priv = test->priv;
 423	struct cs_dsp *dsp = priv->dsp;
 424	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 425	struct cs_dsp_mock_wmfw_builder *builder[3];
 426	unsigned int reg, alg_base_words;
 427	struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
 428	struct firmware *wmfw;
 429	u32 *reg_vals[3], *readback;
 430	int i;
 431
 432	static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(builder));
 433	static_assert(ARRAY_SIZE(reg_vals) == ARRAY_SIZE(builder));
 434	static_assert(ARRAY_SIZE(cs_dsp_ctl_cache_test_fw_names) >= ARRAY_SIZE(builder));
 435
 436	/* Create an identical control in each firmware but with different alg id */
 437	for (i = 0; i < ARRAY_SIZE(builder); i++) {
 438		builder[i] = _create_dummy_wmfw(test);
 439		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder[i]);
 440
 441		cs_dsp_mock_wmfw_start_alg_info_block(builder[i],
 442						      cs_dsp_ctl_cache_test_algs[i].id,
 443						      "dummyalg", NULL);
 444		cs_dsp_mock_wmfw_add_coeff_desc(builder[i], &def);
 445		cs_dsp_mock_wmfw_end_alg_info_block(builder[i]);
 446	}
 447
 448	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 449		reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 450		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
 451	}
 452
 453	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 454	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 455
 456	/*
 457	 * For each firmware create random content in the register backing
 458	 * the control. Then download, start, stop and power-down.
 459	 */
 460	for (i = 0; i < ARRAY_SIZE(builder); i++) {
 461		alg_base_words = _get_alg_mem_base_words(test, i, def.mem_type);
 462		reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
 463		reg += (alg_base_words + def.offset_dsp_words) *
 464			cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 465
 466		get_random_bytes(reg_vals[i], def.length_bytes);
 467		regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes);
 468		wmfw = cs_dsp_mock_wmfw_get_firmware(builder[i]);
 469		KUNIT_ASSERT_EQ(test,
 470				cs_dsp_power_up(dsp, wmfw,
 471						cs_dsp_ctl_cache_test_fw_names[i],
 472						NULL, NULL,
 473						cs_dsp_ctl_cache_test_fw_names[i]),
 474				0);
 475		KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 476		cs_dsp_stop(dsp);
 477		cs_dsp_power_down(dsp);
 478	}
 479
 480	/* There should now be 3 controls */
 481	KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
 482
 483	/*
 484	 * There's no requirement for the control list to be in any
 485	 * particular order, so don't assume the order.
 486	 */
 487	for (i = 0; i < ARRAY_SIZE(ctl); i++)
 488		ctl[i] = NULL;
 489
 490	list_for_each_entry(walkctl, &dsp->ctl_list, list) {
 491		if (cs_dsp_ctl_cache_test_algs[0].id == walkctl->alg_region.alg)
 492			ctl[0] = walkctl;
 493		else if (cs_dsp_ctl_cache_test_algs[1].id == walkctl->alg_region.alg)
 494			ctl[1] = walkctl;
 495		else if (cs_dsp_ctl_cache_test_algs[2].id == walkctl->alg_region.alg)
 496			ctl[2] = walkctl;
 497	}
 498
 499	KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
 500	KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
 501	KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
 502
 503	/*
 504	 * The data should have been populated into the control cache
 505	 * so should be readable through the control.
 506	 */
 507	KUNIT_EXPECT_EQ(test,
 508			cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
 509			0);
 510	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
 511
 512	KUNIT_EXPECT_EQ(test,
 513			cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
 514			0);
 515	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
 516
 517	KUNIT_EXPECT_EQ(test,
 518			cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, def.length_bytes),
 519			0);
 520	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
 521}
 522
 523/*
 524 * Firmware with controls at the same position in different memories.
 525 * The control cache should be initialized with content from the
 526 * correct memory region.
 527 */
 528static void cs_dsp_ctl_cache_init_multiple_mems(struct kunit *test)
 529{
 530	struct cs_dsp_test *priv = test->priv;
 531	struct cs_dsp *dsp = priv->dsp;
 532	struct cs_dsp_test_local *local = priv->local;
 533	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 534	unsigned int reg, alg_base_words;
 535	struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
 536	struct firmware *wmfw;
 537	u32 *reg_vals[3], *readback;
 538	int i;
 539
 540	static_assert(ARRAY_SIZE(ctl) ==  ARRAY_SIZE(reg_vals));
 541
 542	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 543		reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 544		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
 545		get_random_bytes(reg_vals[i], def.length_bytes);
 546	}
 547
 548	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 549	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 550
 551	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 552					      cs_dsp_ctl_cache_test_algs[0].id,
 553					      "dummyalg", NULL);
 554
 555	/* Create controls identical except for memory region */
 556	def.mem_type = WMFW_ADSP2_YM;
 557	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 558
 559	def.mem_type = WMFW_ADSP2_XM;
 560	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 561
 562	if (cs_dsp_mock_has_zm(priv)) {
 563		def.mem_type = WMFW_ADSP2_ZM;
 564		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 565	}
 566
 567	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 568
 569	/* Create random content in the registers backing each control */
 570	alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_YM);
 571	reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
 572	reg += (alg_base_words + def.offset_dsp_words) *
 573		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 574	regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes);
 575
 576	alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_XM);
 577	reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM);
 578	reg += (alg_base_words + def.offset_dsp_words) *
 579		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 580	regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes);
 581
 582	if (cs_dsp_mock_has_zm(priv)) {
 583		alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_ZM);
 584		reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM);
 585		reg += (alg_base_words + def.offset_dsp_words) *
 586			cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 587		regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes);
 588	}
 589
 590	/* Download, run, stop and power-down the firmware */
 591	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
 592	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 593	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 594	cs_dsp_stop(dsp);
 595	cs_dsp_power_down(dsp);
 596
 597	/* There should now be 2 or 3 controls */
 598	KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list),
 599			cs_dsp_mock_has_zm(priv) ? 3 : 2);
 600
 601	/*
 602	 * There's no requirement for the control list to be in any
 603	 * particular order, so don't assume the order.
 604	 */
 605	for (i = 0; i < ARRAY_SIZE(ctl); i++)
 606		ctl[i] = NULL;
 607
 608	list_for_each_entry(walkctl, &dsp->ctl_list, list) {
 609		if (walkctl->alg_region.type == WMFW_ADSP2_YM)
 610			ctl[0] = walkctl;
 611		if (walkctl->alg_region.type == WMFW_ADSP2_XM)
 612			ctl[1] = walkctl;
 613		if (walkctl->alg_region.type == WMFW_ADSP2_ZM)
 614			ctl[2] = walkctl;
 615	}
 616
 617
 618	/*
 619	 * The data should have been populated into the control cache
 620	 * so should be readable through the control.
 621	 */
 622	KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
 623	KUNIT_EXPECT_EQ(test,
 624			cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
 625			0);
 626	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
 627
 628	KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
 629	KUNIT_EXPECT_EQ(test,
 630			cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
 631			0);
 632	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
 633
 634	if (cs_dsp_mock_has_zm(priv)) {
 635		KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
 636		KUNIT_EXPECT_EQ(test,
 637				cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
 638								def.length_bytes),
 639				0);
 640		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
 641	}
 642}
 643
 644/*
 645 * Firmware with controls at the same position in different algorithms
 646 * The control cache should be initialized with content from the
 647 * memory of the algorithm it points to.
 648 */
 649static void cs_dsp_ctl_cache_init_multiple_algs(struct kunit *test)
 650{
 651	struct cs_dsp_test *priv = test->priv;
 652	struct cs_dsp *dsp = priv->dsp;
 653	struct cs_dsp_test_local *local = priv->local;
 654	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 655	unsigned int reg, alg_base_words;
 656	struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
 657	struct firmware *wmfw;
 658	u32 *reg_vals[3], *readback;
 659	int i;
 660
 661	static_assert(ARRAY_SIZE(ctl) ==  ARRAY_SIZE(reg_vals));
 662	static_assert(ARRAY_SIZE(reg_vals) <= ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
 663
 664	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 665		reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 666		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
 667		get_random_bytes(reg_vals[i], def.length_bytes);
 668	}
 669
 670	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 671	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 672
 673	/* Create controls identical except for algorithm */
 674	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 675		cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 676						      cs_dsp_ctl_cache_test_algs[i].id,
 677						      "dummyalg", NULL);
 678		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 679		cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 680	}
 681
 682	/* Create random content in the registers backing each control */
 683	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 684		alg_base_words = _get_alg_mem_base_words(test, i, def.mem_type);
 685		reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
 686		reg += (alg_base_words + def.offset_dsp_words) *
 687			cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 688		regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes);
 689	}
 690
 691	/* Download, run, stop and power-down the firmware */
 692	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
 693	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 694	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 695	cs_dsp_stop(dsp);
 696	cs_dsp_power_down(dsp);
 697
 698	/* There should now be 3 controls */
 699	KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
 700
 701	/*
 702	 * There's no requirement for the control list to be in any
 703	 * particular order, so don't assume the order.
 704	 */
 705	for (i = 0; i < ARRAY_SIZE(ctl); i++)
 706		ctl[i] = NULL;
 707
 708	list_for_each_entry(walkctl, &dsp->ctl_list, list) {
 709		if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[0].id)
 710			ctl[0] = walkctl;
 711		if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[1].id)
 712			ctl[1] = walkctl;
 713		if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[2].id)
 714			ctl[2] = walkctl;
 715	}
 716
 717	KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
 718	KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
 719	KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
 720
 721	/*
 722	 * The data should have been populated into the control cache
 723	 * so should be readable through the control.
 724	 */
 725	KUNIT_EXPECT_EQ(test,
 726			cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
 727			0);
 728	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
 729
 730	KUNIT_EXPECT_EQ(test,
 731			cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
 732			0);
 733	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
 734
 735	KUNIT_EXPECT_EQ(test,
 736			cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
 737							def.length_bytes),
 738			0);
 739	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
 740}
 741
 742/*
 743 * Firmware with controls in the same algorithm and memory but at
 744 * different offsets.
 745 * The control cache should be initialized with content from the
 746 * correct offset.
 747 * Only for wmfw format V2 and later. V1 only supports one control per
 748 * memory per algorithm.
 749 */
 750static void cs_dsp_ctl_cache_init_multiple_offsets(struct kunit *test)
 751{
 752	struct cs_dsp_test *priv = test->priv;
 753	struct cs_dsp *dsp = priv->dsp;
 754	struct cs_dsp_test_local *local = priv->local;
 755	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 756	unsigned int reg, alg_base_words, alg_base_reg;
 757	struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
 758	struct firmware *wmfw;
 759	u32 *reg_vals[3], *readback;
 760	int i;
 761
 762	static_assert(ARRAY_SIZE(ctl) ==  ARRAY_SIZE(reg_vals));
 763	static_assert(ARRAY_SIZE(reg_vals) <= ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
 764
 765	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
 766		reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 767		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
 768		get_random_bytes(reg_vals[i], def.length_bytes);
 769	}
 770
 771	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 772	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 773
 774	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 775					      cs_dsp_ctl_cache_test_algs[0].id,
 776					      "dummyalg", NULL);
 777
 778	/* Create controls identical except for offset */
 779	def.offset_dsp_words = 0;
 780	def.shortname = "CtlA";
 781	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 782
 783	def.offset_dsp_words = 5;
 784	def.shortname = "CtlB";
 785	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 786
 787	def.offset_dsp_words = 8;
 788	def.shortname = "CtlC";
 789	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 790
 791	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 792
 793	/* Create random content in the registers backing each control */
 794	alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type);
 795	alg_base_reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
 796	alg_base_reg += alg_base_words * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 797
 798	reg = alg_base_reg;
 799	regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes);
 800	reg = alg_base_reg + (5 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv));
 801	regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes);
 802	reg = alg_base_reg + (8 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv));
 803	regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes);
 804
 805	/* Download, run, stop and power-down the firmware */
 806	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
 807	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 808	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 809	cs_dsp_stop(dsp);
 810	cs_dsp_power_down(dsp);
 811
 812	/* There should now be 3 controls */
 813	KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
 814
 815	/*
 816	 * There's no requirement for the control list to be in any
 817	 * particular order, so don't assume the order.
 818	 */
 819	for (i = 0; i < ARRAY_SIZE(ctl); i++)
 820		ctl[i] = NULL;
 821
 822	list_for_each_entry(walkctl, &dsp->ctl_list, list) {
 823		if (walkctl->offset == 0)
 824			ctl[0] = walkctl;
 825		if (walkctl->offset == 5)
 826			ctl[1] = walkctl;
 827		if (walkctl->offset == 8)
 828			ctl[2] = walkctl;
 829	}
 830
 831	KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
 832	KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
 833	KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
 834
 835	/*
 836	 * The data should have been populated into the control cache
 837	 * so should be readable through the control.
 838	 */
 839	KUNIT_EXPECT_EQ(test,
 840			cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
 841			0);
 842	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
 843
 844	KUNIT_EXPECT_EQ(test,
 845			cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
 846			0);
 847	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
 848
 849	KUNIT_EXPECT_EQ(test,
 850			cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
 851							def.length_bytes),
 852			0);
 853	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
 854}
 855
 856/*
 857 * Read from a cached control before the firmware is started.
 858 * Should return the data in the cache.
 859 */
 860static void cs_dsp_ctl_cache_read_not_started(struct kunit *test)
 861{
 862	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
 863	struct cs_dsp_test *priv = test->priv;
 864	struct cs_dsp_test_local *local = priv->local;
 865	struct cs_dsp *dsp = priv->dsp;
 866	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 867	int alg_idx = _find_alg_entry(test, param->alg_id);
 868	unsigned int reg, alg_base_words;
 869	struct cs_dsp_coeff_ctl *ctl;
 870	struct firmware *wmfw;
 871	u32 *reg_vals, *readback;
 872
 873	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 874	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 875
 876	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 877	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 878
 879	/* Create some DSP data to be read into the control cache */
 880	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 881	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 882	reg += (alg_base_words + param->offs_words) *
 883		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 884	get_random_bytes(reg_vals, param->len_bytes);
 885	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 886
 887	/* Create control pointing to this data */
 888	def.flags = param->flags;
 889	def.mem_type = param->mem_type;
 890	def.offset_dsp_words = param->offs_words;
 891	def.length_bytes = param->len_bytes;
 892
 893	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 894					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
 895					      "dummyalg", NULL);
 896	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 897	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 898
 899	/* Power-up DSP but don't start firmware */
 900	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 901	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 902
 903	/* Drop expected writes and the regmap cache should be clean */
 904	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 905	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 906	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 907
 908	/* Control should readback the data from the control cache */
 909	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 910	KUNIT_ASSERT_NOT_NULL(test, ctl);
 911	KUNIT_EXPECT_EQ(test,
 912			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
 913			0);
 914	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
 915}
 916
 917/*
 918 * Read from a cached control after the firmware has been stopped.
 919 * Should return the data in the cache.
 920 */
 921static void cs_dsp_ctl_cache_read_stopped(struct kunit *test)
 922{
 923	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
 924	struct cs_dsp_test *priv = test->priv;
 925	struct cs_dsp_test_local *local = priv->local;
 926	struct cs_dsp *dsp = priv->dsp;
 927	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 928	int alg_idx = _find_alg_entry(test, param->alg_id);
 929	unsigned int reg, alg_base_words;
 930	struct cs_dsp_coeff_ctl *ctl;
 931	struct firmware *wmfw;
 932	u32 *reg_vals, *readback;
 933
 934	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 935	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 936
 937	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 938	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 939
 940	/* Create some DSP data to be read into the control cache */
 941	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 942	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 943	reg += (alg_base_words + param->offs_words) *
 944		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 945	get_random_bytes(reg_vals, param->len_bytes);
 946	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 947
 948	/* Create control pointing to this data */
 949	def.flags = param->flags;
 950	def.mem_type = param->mem_type;
 951	def.offset_dsp_words = param->offs_words;
 952	def.length_bytes = param->len_bytes;
 953
 954	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 955					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
 956					      "dummyalg", NULL);
 957	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 958	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 959
 960	/* Power-up DSP */
 961	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 962	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 963
 964	/* Start and stop the firmware */
 965	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 966	cs_dsp_stop(dsp);
 967
 968	/* Drop expected writes and the regmap cache should be clean */
 969	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 970	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 971	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 972
 973	/* Control should readback the data from the control cache */
 974	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 975	KUNIT_ASSERT_NOT_NULL(test, ctl);
 976	KUNIT_EXPECT_EQ(test,
 977			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
 978			0);
 979	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
 980}
 981
 982/*
 983 * Read from a cached control after the DSP has been powered-up and
 984 * then powered-down without running.
 985 * Should return the data in the cache.
 986 */
 987static void cs_dsp_ctl_cache_read_powered_down(struct kunit *test)
 988{
 989	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
 990	struct cs_dsp_test *priv = test->priv;
 991	struct cs_dsp_test_local *local = priv->local;
 992	struct cs_dsp *dsp = priv->dsp;
 993	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 994	int alg_idx = _find_alg_entry(test, param->alg_id);
 995	unsigned int reg, alg_base_words;
 996	struct cs_dsp_coeff_ctl *ctl;
 997	struct firmware *wmfw;
 998	u32 *reg_vals, *readback;
 999
1000	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1001	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1002
1003	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1004	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1005
1006	/* Create some DSP data to be read into the control cache */
1007	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1008	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1009	reg += (alg_base_words + param->offs_words) *
1010		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1011	get_random_bytes(reg_vals, param->len_bytes);
1012	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1013
1014	/* Create control pointing to this data */
1015	def.flags = param->flags;
1016	def.mem_type = param->mem_type;
1017	def.offset_dsp_words = param->offs_words;
1018	def.length_bytes = param->len_bytes;
1019
1020	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1021					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1022					      "dummyalg", NULL);
1023	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1024	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1025
1026	/* Power-up DSP then power-down */
1027	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1028	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1029	cs_dsp_power_down(dsp);
1030
1031	/* Drop expected writes and the regmap cache should be clean */
1032	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1033	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1034	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1035
1036	/* Control should readback the data from the control cache */
1037	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1038	KUNIT_ASSERT_NOT_NULL(test, ctl);
1039	KUNIT_EXPECT_EQ(test,
1040			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1041			0);
1042	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1043}
1044
1045/*
1046 * Read from a cached control after the firmware has been run and
1047 * stopped, then the DSP has been powered-down.
1048 * Should return the data in the cache.
1049 */
1050static void cs_dsp_ctl_cache_read_stopped_powered_down(struct kunit *test)
1051{
1052	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1053	struct cs_dsp_test *priv = test->priv;
1054	struct cs_dsp_test_local *local = priv->local;
1055	struct cs_dsp *dsp = priv->dsp;
1056	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1057	int alg_idx = _find_alg_entry(test, param->alg_id);
1058	unsigned int reg, alg_base_words;
1059	struct cs_dsp_coeff_ctl *ctl;
1060	struct firmware *wmfw;
1061	u32 *reg_vals, *readback;
1062
1063	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1064	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1065
1066	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1067	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1068
1069	/* Create some DSP data to be read into the control cache */
1070	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1071	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1072	reg += (alg_base_words + param->offs_words) *
1073		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1074	get_random_bytes(reg_vals, param->len_bytes);
1075	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1076
1077	/* Create control pointing to this data */
1078	def.flags = param->flags;
1079	def.mem_type = param->mem_type;
1080	def.offset_dsp_words = param->offs_words;
1081	def.length_bytes = param->len_bytes;
1082
1083	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1084					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1085					      "dummyalg", NULL);
1086	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1087	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1088
1089	/* Power-up DSP */
1090	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1091	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1092
1093	/* Start and stop the firmware then power-down */
1094	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1095	cs_dsp_stop(dsp);
1096	cs_dsp_power_down(dsp);
1097
1098	/* Drop expected writes and the regmap cache should be clean */
1099	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1100	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1101	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1102
1103	/* Control should readback the data from the control cache */
1104	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1105	KUNIT_ASSERT_NOT_NULL(test, ctl);
1106	KUNIT_EXPECT_EQ(test,
1107			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1108			0);
1109	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1110}
1111
1112/*
1113 * Read from a cached control when a different firmware is currently
1114 * loaded into the DSP.
1115 * Should return the data in the cache.
1116 */
1117static void cs_dsp_ctl_cache_read_not_current_loaded_fw(struct kunit *test)
1118{
1119	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1120	struct cs_dsp_test *priv = test->priv;
1121	struct cs_dsp_test_local *local = priv->local;
1122	struct cs_dsp *dsp = priv->dsp;
1123	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1124	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1125	int alg_idx = _find_alg_entry(test, param->alg_id);
1126	unsigned int reg, alg_base_words;
1127	struct cs_dsp_coeff_ctl *ctl;
1128	struct firmware *wmfw;
1129	u32 *reg_vals, *readback;
1130
1131	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1132	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1133
1134	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1135	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1136
1137	/* Create some DSP data to be read into the control cache */
1138	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1139	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1140	reg += (alg_base_words + param->offs_words) *
1141		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1142	get_random_bytes(reg_vals, param->len_bytes);
1143	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1144
1145	/* Create control pointing to this data */
1146	def.flags = param->flags;
1147	def.mem_type = param->mem_type;
1148	def.offset_dsp_words = param->offs_words;
1149	def.length_bytes = param->len_bytes;
1150
1151	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1152					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1153					      "dummyalg", NULL);
1154	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1155	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1156
1157	/* Power-up DSP */
1158	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1159	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1160
1161	/* Power-down DSP then power-up with a different firmware */
1162	cs_dsp_power_down(dsp);
1163	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1164	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1165
1166	/* Drop expected writes and the regmap cache should be clean */
1167	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1168	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1169	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1170
1171	/* Control should readback the data from the control cache */
1172	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1173	KUNIT_ASSERT_NOT_NULL(test, ctl);
1174	KUNIT_EXPECT_EQ(test,
1175			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1176			0);
1177	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1178}
1179
1180/*
1181 * Read from a cached control when a different firmware is currently
1182 * running.
1183 * Should return the data in the cache.
1184 */
1185static void cs_dsp_ctl_cache_read_not_current_running_fw(struct kunit *test)
1186{
1187	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1188	struct cs_dsp_test *priv = test->priv;
1189	struct cs_dsp_test_local *local = priv->local;
1190	struct cs_dsp *dsp = priv->dsp;
1191	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1192	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1193	int alg_idx = _find_alg_entry(test, param->alg_id);
1194	unsigned int reg, alg_base_words;
1195	struct cs_dsp_coeff_ctl *ctl;
1196	struct firmware *wmfw;
1197	u32 *reg_vals, *readback;
1198
1199	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1200	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1201
1202	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1203	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1204
1205	/* Create some DSP data to be read into the control cache */
1206	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1207	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1208	reg += (alg_base_words + param->offs_words) *
1209		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1210	get_random_bytes(reg_vals, param->len_bytes);
1211	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1212
1213	/* Create control pointing to this data */
1214	def.flags = param->flags;
1215	def.mem_type = param->mem_type;
1216	def.offset_dsp_words = param->offs_words;
1217	def.length_bytes = param->len_bytes;
1218
1219	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1220					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1221					      "dummyalg", NULL);
1222	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1223	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1224
1225	/* Power-up DSP then power-down */
1226	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1227	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1228	cs_dsp_power_down(dsp);
1229
1230	/* Power-up with a different firmware and run it */
1231	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1232	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1233	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1234	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1235
1236	/* Drop expected writes and the regmap cache should be clean */
1237	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1238	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1239	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1240
1241	/* Control should readback the data from the control cache */
1242	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1243	KUNIT_ASSERT_NOT_NULL(test, ctl);
1244	KUNIT_EXPECT_EQ(test,
1245			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1246			0);
1247	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1248}
1249
1250/*
1251 * Read from a cached control with non-zero flags while the firmware is
1252 * running.
1253 * Should return the data in the cache, not from the registers.
1254 */
1255static void cs_dsp_ctl_cache_read_running(struct kunit *test)
1256{
1257	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1258	struct cs_dsp_test *priv = test->priv;
1259	struct cs_dsp_test_local *local = priv->local;
1260	struct cs_dsp *dsp = priv->dsp;
1261	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1262	int alg_idx = _find_alg_entry(test, param->alg_id);
1263	unsigned int reg, alg_base_words;
1264	struct cs_dsp_coeff_ctl *ctl;
1265	struct firmware *wmfw;
1266	u32 *init_reg_vals, *new_reg_vals, *readback;
1267
1268	init_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1269	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals);
1270
1271	new_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1272	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals);
1273
1274	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1275	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1276
1277	/* Create data in the registers backing the control */
1278	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1279	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1280	reg += (alg_base_words + param->offs_words) *
1281		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1282	get_random_bytes(init_reg_vals, param->len_bytes);
1283	regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1284
1285	/* Create control pointing to this data */
1286	def.flags = param->flags;
1287	def.mem_type = param->mem_type;
1288	def.offset_dsp_words = param->offs_words;
1289	def.length_bytes = param->len_bytes;
1290
1291	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1292					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1293					      "dummyalg", NULL);
1294	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1295	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1296
1297	/* Power-up DSP */
1298	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1299	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1300
1301	/* Start the firmware running */
1302	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1303	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1304
1305	/*
1306	 * Change the values in the registers backing the control then drop
1307	 * them from the regmap cache. This allows checking that the control
1308	 * read is returning values from the control cache and not accessing
1309	 * the registers.
1310	 */
1311	KUNIT_ASSERT_EQ(test,
1312			regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes),
1313			0);
1314	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1315
1316	/* Control should readback the origin data from its cache */
1317	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1318	KUNIT_ASSERT_NOT_NULL(test, ctl);
1319	KUNIT_EXPECT_EQ(test,
1320			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1321			0);
1322	KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes);
1323
1324	/* Stop and power-down the DSP */
1325	kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1326	cs_dsp_power_down(dsp);
1327
1328	/* Control should readback from the cache */
1329	KUNIT_EXPECT_EQ(test,
1330			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1331			0);
1332	KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes);
1333}
1334
1335/*
1336 * Read from a cached control with flags == 0 while the firmware is
1337 * running.
1338 * Should behave as volatile and read from the registers.
1339 * (This is for backwards compatibility with old firmware versions)
1340 */
1341static void cs_dsp_ctl_cache_read_running_zero_flags(struct kunit *test)
1342{
1343	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1344	struct cs_dsp_test *priv = test->priv;
1345	struct cs_dsp_test_local *local = priv->local;
1346	struct cs_dsp *dsp = priv->dsp;
1347	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1348	int alg_idx = _find_alg_entry(test, param->alg_id);
1349	unsigned int reg, alg_base_words;
1350	struct cs_dsp_coeff_ctl *ctl;
1351	struct firmware *wmfw;
1352	u32 *init_reg_vals, *new_reg_vals, *readback;
1353
1354	init_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1355	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals);
1356
1357	new_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1358	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals);
1359
1360	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1361	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1362
1363	/* Zero-fill the registers backing the control */
1364	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1365	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1366	reg += (alg_base_words + param->offs_words) *
1367		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1368	regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1369
1370	/* Create control pointing to this data */
1371	def.flags = 0;
1372	def.mem_type = param->mem_type;
1373	def.offset_dsp_words = param->offs_words;
1374	def.length_bytes = param->len_bytes;
1375
1376	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1377					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1378					      "dummyalg", NULL);
1379	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1380	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1381
1382	/* Power-up DSP */
1383	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1384	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1385
1386	/* Start the firmware running */
1387	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1388	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1389
1390	/* Change the values in the registers backing the control */
1391	get_random_bytes(new_reg_vals, param->len_bytes);
1392	regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes);
1393
1394	/* Control should readback the new data from the registers */
1395	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1396	KUNIT_ASSERT_NOT_NULL(test, ctl);
1397	KUNIT_EXPECT_EQ(test,
1398			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1399			0);
1400	KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes);
1401
1402	/* Stop and power-down the DSP */
1403	kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1404	cs_dsp_power_down(dsp);
1405
1406	/* Change the values in the registers backing the control */
1407	regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1408
1409	/* Control should readback from the cache */
1410	KUNIT_EXPECT_EQ(test,
1411			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1412			0);
1413	KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes);
1414}
1415
1416/*
1417 * Write to a cached control while the firmware is running.
1418 * This should be a writethrough operation, writing to the cache and
1419 * the registers.
1420 */
1421static void cs_dsp_ctl_cache_writethrough(struct kunit *test)
1422{
1423	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1424	struct cs_dsp_test *priv = test->priv;
1425	struct cs_dsp_test_local *local = priv->local;
1426	struct cs_dsp *dsp = priv->dsp;
1427	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1428	int alg_idx = _find_alg_entry(test, param->alg_id);
1429	unsigned int reg, alg_base_words;
1430	struct cs_dsp_coeff_ctl *ctl;
1431	struct firmware *wmfw;
1432	u32 *reg_vals, *readback;
1433
1434	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1435	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1436
1437	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1438	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1439
1440	/* Create some DSP data to be read into the control cache */
1441	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1442	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1443	reg += (alg_base_words + param->offs_words) *
1444		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1445	memset(reg_vals, 0, param->len_bytes);
1446	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1447
1448	/* Create control pointing to this data */
1449	def.flags = param->flags;
1450	def.mem_type = param->mem_type;
1451	def.offset_dsp_words = param->offs_words;
1452	def.length_bytes = param->len_bytes;
1453
1454	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1455					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1456					      "dummyalg", NULL);
1457	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1458	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1459
1460	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1461	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1462
1463	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1464	KUNIT_ASSERT_NOT_NULL(test, ctl);
1465
1466	/* Start the firmware and add an action to stop it during cleanup */
1467	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1468	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1469
1470	/* Write new data to the control, it should be written to the registers */
1471	get_random_bytes(reg_vals, param->len_bytes);
1472	KUNIT_EXPECT_EQ(test,
1473			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1474			1);
1475	KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1476	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1477}
1478
1479/*
1480 * Write unchanged data to a cached control while the firmware is running.
1481 * The control write should return 0 to indicate that the content
1482 * didn't change.
1483 */
1484static void cs_dsp_ctl_cache_writethrough_unchanged(struct kunit *test)
1485{
1486	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1487	struct cs_dsp_test *priv = test->priv;
1488	struct cs_dsp_test_local *local = priv->local;
1489	struct cs_dsp *dsp = priv->dsp;
1490	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1491	int alg_idx = _find_alg_entry(test, param->alg_id);
1492	unsigned int reg, alg_base_words;
1493	struct cs_dsp_coeff_ctl *ctl;
1494	struct firmware *wmfw;
1495	u32 *reg_vals, *readback;
1496
1497	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1498	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1499
1500	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1501	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1502
1503	/* Create some DSP data to be read into the control cache */
1504	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1505	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1506	reg += (alg_base_words + param->offs_words) *
1507		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1508	get_random_bytes(reg_vals, param->len_bytes);
1509	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1510
1511	/* Create control pointing to this data */
1512	def.flags = param->flags;
1513	def.mem_type = param->mem_type;
1514	def.offset_dsp_words = param->offs_words;
1515	def.length_bytes = param->len_bytes;
1516
1517	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1518					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1519					      "dummyalg", NULL);
1520	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1521	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1522
1523	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1524	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1525
1526	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1527	KUNIT_ASSERT_NOT_NULL(test, ctl);
1528
1529	/* Start the firmware and add an action to stop it during cleanup */
1530	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1531	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1532
1533	/*
1534	 * If the control is write-only the cache will have been zero-initialized
1535	 * so the first write will always indicate a change.
1536	 */
1537	if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) {
1538		KUNIT_EXPECT_EQ(test,
1539				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1540								 param->len_bytes),
1541				1);
1542	}
1543
1544	/*
1545	 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl()
1546	 * should return 0 to indicate the content didn't change.
1547	 */
1548	KUNIT_EXPECT_EQ(test,
1549			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1550			0);
1551	KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1552	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1553}
1554
1555/*
1556 * Write unchanged data to a cached control while the firmware is not started.
1557 * The control write should return 0 to indicate that the cache content
1558 * didn't change.
1559 */
1560static void cs_dsp_ctl_cache_write_unchanged_not_started(struct kunit *test)
1561{
1562	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1563	struct cs_dsp_test *priv = test->priv;
1564	struct cs_dsp_test_local *local = priv->local;
1565	struct cs_dsp *dsp = priv->dsp;
1566	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1567	int alg_idx = _find_alg_entry(test, param->alg_id);
1568	unsigned int reg, alg_base_words;
1569	struct cs_dsp_coeff_ctl *ctl;
1570	struct firmware *wmfw;
1571	u32 *reg_vals, *readback;
1572
1573	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1574	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1575
1576	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1577	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1578
1579	/* Create some DSP data to be read into the control cache */
1580	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1581	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1582	reg += (alg_base_words + param->offs_words) *
1583		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1584	get_random_bytes(reg_vals, param->len_bytes);
1585	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1586
1587	/* Create control pointing to this data */
1588	def.flags = param->flags;
1589	def.mem_type = param->mem_type;
1590	def.offset_dsp_words = param->offs_words;
1591	def.length_bytes = param->len_bytes;
1592
1593	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1594					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1595					      "dummyalg", NULL);
1596	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1597	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1598
1599	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1600	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1601
1602	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1603	KUNIT_ASSERT_NOT_NULL(test, ctl);
1604
1605	/*
1606	 * If the control is write-only the cache will have been zero-initialized
1607	 * so the first write will always indicate a change.
1608	 */
1609	if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) {
1610		KUNIT_EXPECT_EQ(test,
1611				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1612								 param->len_bytes),
1613				1);
1614	}
1615
1616	/*
1617	 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl()
1618	 * should return 0 to indicate the content didn't change.
1619	 */
1620	KUNIT_EXPECT_EQ(test,
1621			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1622			0);
1623	KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1624	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1625}
1626
1627/*
1628 * Write to a cached control while the firmware is loaded but not
1629 * started.
1630 * This should write to the cache only.
1631 */
1632static void cs_dsp_ctl_cache_write_not_started(struct kunit *test)
1633{
1634	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1635	struct cs_dsp_test *priv = test->priv;
1636	struct cs_dsp_test_local *local = priv->local;
1637	struct cs_dsp *dsp = priv->dsp;
1638	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1639	int alg_idx = _find_alg_entry(test, param->alg_id);
1640	unsigned int reg, alg_base_words;
1641	struct cs_dsp_coeff_ctl *ctl;
1642	struct firmware *wmfw;
1643	u32 *reg_vals, *readback;
1644
1645	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1646	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1647
1648	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1649	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1650
1651	/* Create some DSP data to be read into the control cache */
1652	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1653	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1654	reg += (alg_base_words + param->offs_words) *
1655		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1656	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1657
1658	/* Create control pointing to this data */
1659	def.flags = param->flags;
1660	def.mem_type = param->mem_type;
1661	def.offset_dsp_words = param->offs_words;
1662	def.length_bytes = param->len_bytes;
1663
1664	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1665					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1666					      "dummyalg", NULL);
1667	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1668	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1669
1670	/* Power-up DSP but don't start firmware */
1671	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1672	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1673
1674	/* Drop expected writes and the regmap cache should be clean */
1675	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1676	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1677	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1678
1679	/* Write new data to the control, it should not be written to the registers */
1680	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1681	KUNIT_ASSERT_NOT_NULL(test, ctl);
1682
1683	get_random_bytes(reg_vals, param->len_bytes);
1684	KUNIT_EXPECT_EQ(test,
1685			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1686			1);
1687
1688	/* Registers should not have been written so regmap cache should still be clean */
1689	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1690
1691	/* Control should readback the new data from the control cache */
1692	KUNIT_EXPECT_EQ(test,
1693			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1694			0);
1695	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1696}
1697
1698/*
1699 * Write to a cached control after the firmware has been loaded,
1700 * started and stopped.
1701 * This should write to the cache only.
1702 */
1703static void cs_dsp_ctl_cache_write_stopped(struct kunit *test)
1704{
1705	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1706	struct cs_dsp_test *priv = test->priv;
1707	struct cs_dsp_test_local *local = priv->local;
1708	struct cs_dsp *dsp = priv->dsp;
1709	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1710	int alg_idx = _find_alg_entry(test, param->alg_id);
1711	unsigned int reg, alg_base_words;
1712	struct cs_dsp_coeff_ctl *ctl;
1713	struct firmware *wmfw;
1714	u32 *reg_vals, *readback;
1715
1716	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1717	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1718
1719	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1720	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1721
1722	/* Create some DSP data to be read into the control cache */
1723	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1724	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1725	reg += (alg_base_words + param->offs_words) *
1726		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1727	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1728
1729	/* Create control pointing to this data */
1730	def.flags = param->flags;
1731	def.mem_type = param->mem_type;
1732	def.offset_dsp_words = param->offs_words;
1733	def.length_bytes = param->len_bytes;
1734
1735	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1736					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1737					      "dummyalg", NULL);
1738	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1739	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1740
1741	/* Power-up DSP */
1742	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1743	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1744
1745	/* Start and stop the firmware */
1746	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1747	cs_dsp_stop(dsp);
1748
1749	/* Drop expected writes and the regmap cache should be clean */
1750	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1751	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1752	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1753
1754	/* Write new data to the control, it should not be written to the registers */
1755	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1756	KUNIT_ASSERT_NOT_NULL(test, ctl);
1757
1758	get_random_bytes(reg_vals, param->len_bytes);
1759	KUNIT_EXPECT_EQ(test,
1760			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1761			1);
1762
1763	/* Registers should not have been written so regmap cache should still be clean */
1764	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1765
1766	/* Control should readback the new data from the control cache */
1767	KUNIT_EXPECT_EQ(test,
1768			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1769			0);
1770	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1771}
1772
1773/*
1774 * Write to a cached control after the firmware has been loaded,
1775 * then the DSP powered-down.
1776 * This should write to the cache only.
1777 */
1778static void cs_dsp_ctl_cache_write_powered_down(struct kunit *test)
1779{
1780	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1781	struct cs_dsp_test *priv = test->priv;
1782	struct cs_dsp_test_local *local = priv->local;
1783	struct cs_dsp *dsp = priv->dsp;
1784	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1785	int alg_idx = _find_alg_entry(test, param->alg_id);
1786	unsigned int reg, alg_base_words;
1787	struct cs_dsp_coeff_ctl *ctl;
1788	struct firmware *wmfw;
1789	u32 *reg_vals, *readback;
1790
1791	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1792	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1793
1794	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1795	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1796
1797	/* Create some DSP data to be read into the control cache */
1798	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1799	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1800	reg += (alg_base_words + param->offs_words) *
1801		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1802	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1803
1804	/* Create control pointing to this data */
1805	def.flags = param->flags;
1806	def.mem_type = param->mem_type;
1807	def.offset_dsp_words = param->offs_words;
1808	def.length_bytes = param->len_bytes;
1809
1810	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1811					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1812					      "dummyalg", NULL);
1813	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1814	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1815
1816	/* Power-up DSP then power-down */
1817	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1818	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1819	cs_dsp_power_down(dsp);
1820
1821	/* Drop expected writes and the regmap cache should be clean */
1822	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1823	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1824	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1825
1826	/* Write new data to the control, it should not be written to the registers */
1827	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1828	KUNIT_ASSERT_NOT_NULL(test, ctl);
1829
1830	get_random_bytes(reg_vals, param->len_bytes);
1831	KUNIT_EXPECT_EQ(test,
1832			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1833			1);
1834
1835	/* Registers should not have been written so regmap cache should still be clean */
1836	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1837
1838	/* Control should readback the new data from the control cache */
1839	KUNIT_EXPECT_EQ(test,
1840			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1841			0);
1842	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1843}
1844
1845/*
1846 * Write to a cached control after the firmware has been loaded,
1847 * started, stopped, and then the DSP powered-down.
1848 * This should write to the cache only.
1849 */
1850static void cs_dsp_ctl_cache_write_stopped_powered_down(struct kunit *test)
1851{
1852	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1853	struct cs_dsp_test *priv = test->priv;
1854	struct cs_dsp_test_local *local = priv->local;
1855	struct cs_dsp *dsp = priv->dsp;
1856	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1857	int alg_idx = _find_alg_entry(test, param->alg_id);
1858	unsigned int reg, alg_base_words;
1859	struct cs_dsp_coeff_ctl *ctl;
1860	struct firmware *wmfw;
1861	u32 *reg_vals, *readback;
1862
1863	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1864	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1865
1866	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1867	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1868
1869	/* Create some DSP data to be read into the control cache */
1870	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1871	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1872	reg += (alg_base_words + param->offs_words) *
1873		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1874	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1875
1876	/* Create control pointing to this data */
1877	def.flags = param->flags;
1878	def.mem_type = param->mem_type;
1879	def.offset_dsp_words = param->offs_words;
1880	def.length_bytes = param->len_bytes;
1881
1882	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1883					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1884					      "dummyalg", NULL);
1885	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1886	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1887
1888	/* Power-up DSP */
1889	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1890	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1891
1892	/* Start and stop the firmware then power-down */
1893	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1894	cs_dsp_stop(dsp);
1895	cs_dsp_power_down(dsp);
1896
1897	/* Drop expected writes and the regmap cache should be clean */
1898	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1899	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1900	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1901
1902	/* Write new data to the control, it should not be written to the registers */
1903	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1904	KUNIT_ASSERT_NOT_NULL(test, ctl);
1905
1906	get_random_bytes(reg_vals, param->len_bytes);
1907	KUNIT_EXPECT_EQ(test,
1908			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1909			1);
1910
1911	/* Registers should not have been written so regmap cache should still be clean */
1912	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1913
1914	/* Control should readback the new data from the control cache */
1915	KUNIT_EXPECT_EQ(test,
1916			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1917			0);
1918	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1919}
1920
1921/*
1922 * Write to a cached control that is not in the currently loaded firmware.
1923 * This should write to the cache only.
1924 */
1925static void cs_dsp_ctl_cache_write_not_current_loaded_fw(struct kunit *test)
1926{
1927	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1928	struct cs_dsp_test *priv = test->priv;
1929	struct cs_dsp_test_local *local = priv->local;
1930	struct cs_dsp *dsp = priv->dsp;
1931	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1932	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1933	int alg_idx = _find_alg_entry(test, param->alg_id);
1934	unsigned int reg, alg_base_words;
1935	struct cs_dsp_coeff_ctl *ctl;
1936	struct firmware *wmfw;
1937	u32 *reg_vals, *readback;
1938
1939	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1940	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1941
1942	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1943	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1944
1945	/* Create some DSP data to be read into the control cache */
1946	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1947	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1948	reg += (alg_base_words + param->offs_words) *
1949		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1950	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1951
1952	/* Create control pointing to this data */
1953	def.flags = param->flags;
1954	def.mem_type = param->mem_type;
1955	def.offset_dsp_words = param->offs_words;
1956	def.length_bytes = param->len_bytes;
1957
1958	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1959					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
1960					      "dummyalg", NULL);
1961	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1962	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1963
1964	/* Power-up DSP */
1965	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1966	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1967
1968	/* Get the control */
1969	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1970	KUNIT_ASSERT_NOT_NULL(test, ctl);
1971
1972	/* Power-down DSP then power-up with a different firmware */
1973	cs_dsp_power_down(dsp);
1974	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1975	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1976
1977	/* Control from unloaded firmware should be disabled */
1978	KUNIT_EXPECT_FALSE(test, ctl->enabled);
1979
1980	/* Drop expected writes and the regmap cache should be clean */
1981	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1982	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1983	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1984
1985	/*
1986	 * It should be possible to write new data to the control from
1987	 * the first firmware. But this should not be written to the
1988	 * registers.
1989	 */
1990	get_random_bytes(reg_vals, param->len_bytes);
1991	KUNIT_EXPECT_EQ(test,
1992			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1993			1);
1994
1995	/* Registers should not have been written so regmap cache should still be clean */
1996	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1997
1998	/* Control should readback the new data from the control cache */
1999	KUNIT_EXPECT_EQ(test,
2000			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2001			0);
2002	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2003}
2004
2005/*
2006 * Write to a cached control that is not in the currently running firmware.
2007 * This should write to the cache only.
2008 */
2009static void cs_dsp_ctl_cache_write_not_current_running_fw(struct kunit *test)
2010{
2011	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2012	struct cs_dsp_test *priv = test->priv;
2013	struct cs_dsp_test_local *local = priv->local;
2014	struct cs_dsp *dsp = priv->dsp;
2015	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2016	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2017	int alg_idx = _find_alg_entry(test, param->alg_id);
2018	unsigned int reg, alg_base_words;
2019	struct cs_dsp_coeff_ctl *ctl;
2020	struct firmware *wmfw;
2021	u32 *reg_vals, *readback;
2022
2023	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2024	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2025
2026	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2027	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2028
2029	/* Create some DSP data to be read into the control cache */
2030	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2031	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2032	reg += (alg_base_words + param->offs_words) *
2033		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2034	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2035
2036	/* Create control pointing to this data */
2037	def.flags = param->flags;
2038	def.mem_type = param->mem_type;
2039	def.offset_dsp_words = param->offs_words;
2040	def.length_bytes = param->len_bytes;
2041
2042	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2043					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2044					      "dummyalg", NULL);
2045	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2046	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2047
2048	/* Power-up DSP then power-down */
2049	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2050	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2051	cs_dsp_power_down(dsp);
2052
2053	/* Get the control */
2054	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2055	KUNIT_ASSERT_NOT_NULL(test, ctl);
2056
2057	/* Power-up with a different firmware and run it */
2058	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2059	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2060	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2061	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2062
2063	/* Control from unloaded firmware should be disabled */
2064	KUNIT_EXPECT_FALSE(test, ctl->enabled);
2065
2066	/* Drop expected writes and the regmap cache should be clean */
2067	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2068	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
2069	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2070
2071	/*
2072	 * It should be possible to write new data to the control from
2073	 * the first firmware. But this should not be written to the
2074	 * registers.
2075	 */
2076	get_random_bytes(reg_vals, param->len_bytes);
2077	KUNIT_EXPECT_EQ(test,
2078			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2079			1);
2080
2081	/* Registers should not have been written so regmap cache should still be clean */
2082	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2083
2084	/* Control should readback the new data from the control cache */
2085	KUNIT_EXPECT_EQ(test,
2086			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2087			0);
2088	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2089}
2090
2091/*
2092 * Write to a cached control before running the firmware.
2093 * The value written to the cache should be synced out to the registers
2094 * backing the control when the firmware is run.
2095 */
2096static void cs_dsp_ctl_cache_sync_write_before_run(struct kunit *test)
2097{
2098	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2099	struct cs_dsp_test *priv = test->priv;
2100	struct cs_dsp_test_local *local = priv->local;
2101	struct cs_dsp *dsp = priv->dsp;
2102	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2103	int alg_idx = _find_alg_entry(test, param->alg_id);
2104	unsigned int reg, alg_base_words;
2105	struct cs_dsp_coeff_ctl *ctl;
2106	struct firmware *wmfw;
2107	u32 *reg_vals, *readback;
2108
2109	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2110	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2111
2112	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2113	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2114
2115	/* Create some DSP data to be read into the control cache */
2116	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2117	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2118	reg += (alg_base_words + param->offs_words) *
2119		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2120	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2121
2122	/* Create control pointing to this data */
2123	def.flags = param->flags;
2124	def.mem_type = param->mem_type;
2125	def.offset_dsp_words = param->offs_words;
2126	def.length_bytes = param->len_bytes;
2127
2128	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2129					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2130					      "dummyalg", NULL);
2131	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2132	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2133
2134	/* Power-up DSP but don't start firmware */
2135	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2136	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2137
2138	/* Write new data to the control, it should not be written to the registers */
2139	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2140	KUNIT_ASSERT_NOT_NULL(test, ctl);
2141
2142	get_random_bytes(reg_vals, param->len_bytes);
2143	KUNIT_EXPECT_EQ(test,
2144			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2145			1);
2146
2147	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2148	KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2149
2150	/* Start the firmware and the cached data should be written to registers */
2151	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2152	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2153
2154	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2155	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2156
2157	/* Control should readback the new data from the control cache */
2158	KUNIT_EXPECT_EQ(test,
2159			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2160			0);
2161	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2162}
2163
2164/*
2165 * Write to a cached control while the firmware is running.
2166 * The value written should be synced out to the registers
2167 * backing the control when the firmware is next run.
2168 */
2169static void cs_dsp_ctl_cache_sync_write_while_running(struct kunit *test)
2170{
2171	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2172	struct cs_dsp_test *priv = test->priv;
2173	struct cs_dsp_test_local *local = priv->local;
2174	struct cs_dsp *dsp = priv->dsp;
2175	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2176	int alg_idx = _find_alg_entry(test, param->alg_id);
2177	unsigned int reg, alg_base_words;
2178	struct cs_dsp_coeff_ctl *ctl;
2179	struct firmware *wmfw;
2180	u32 *init_vals, *ctl_vals, *readback;
2181
2182	init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2183	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2184
2185	ctl_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2186	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2187
2188	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2189	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2190
2191	/* Zero-fill the registers backing the control */
2192	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2193	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2194	reg += (alg_base_words + param->offs_words) *
2195		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2196	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2197
2198	/* Create control pointing to this data */
2199	def.flags = param->flags;
2200	def.mem_type = param->mem_type;
2201	def.offset_dsp_words = param->offs_words;
2202	def.length_bytes = param->len_bytes;
2203
2204	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2205					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2206					      "dummyalg", NULL);
2207	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2208	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2209
2210	/* Power-up DSP and start firmware */
2211	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2212	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2213	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2214	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2215
2216	/* Write new data to the control */
2217	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2218	KUNIT_ASSERT_NOT_NULL(test, ctl);
2219
2220	get_random_bytes(ctl_vals, param->len_bytes);
2221	KUNIT_EXPECT_EQ(test,
2222			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2223			1);
2224
2225	/* Stop firmware and zero the registers backing the control */
2226	kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2227	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2228	KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2229	KUNIT_EXPECT_MEMEQ(test, readback, init_vals, param->len_bytes);
2230
2231	/* Start the firmware and the cached data should be written to registers */
2232	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2233	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2234
2235	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2236	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2237
2238	/* Control should readback the new data from the control cache */
2239	KUNIT_EXPECT_EQ(test,
2240			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2241			0);
2242	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2243}
2244
2245/*
2246 * Write to a cached control after stopping the firmware.
2247 * The value written to the cache should be synced out to the registers
2248 * backing the control when the firmware is next run.
2249 */
2250static void cs_dsp_ctl_cache_sync_write_after_stop(struct kunit *test)
2251{
2252	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2253	struct cs_dsp_test *priv = test->priv;
2254	struct cs_dsp_test_local *local = priv->local;
2255	struct cs_dsp *dsp = priv->dsp;
2256	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2257	int alg_idx = _find_alg_entry(test, param->alg_id);
2258	unsigned int reg, alg_base_words;
2259	struct cs_dsp_coeff_ctl *ctl;
2260	struct firmware *wmfw;
2261	u32 *reg_vals, *readback;
2262
2263	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2264	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2265
2266	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2267	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2268
2269	/* Create some DSP data to be read into the control cache */
2270	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2271	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2272	reg += (alg_base_words + param->offs_words) *
2273		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2274	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2275
2276	/* Create control pointing to this data */
2277	def.flags = param->flags;
2278	def.mem_type = param->mem_type;
2279	def.offset_dsp_words = param->offs_words;
2280	def.length_bytes = param->len_bytes;
2281
2282	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2283					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2284					      "dummyalg", NULL);
2285	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2286	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2287
2288	/* Power-up DSP but don't start firmware */
2289	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2290	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2291
2292	/* Start and stop the firmware */
2293	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2294	cs_dsp_stop(dsp);
2295
2296	/* Write new data to the control, it should not be written to the registers */
2297	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2298	KUNIT_ASSERT_NOT_NULL(test, ctl);
2299
2300	get_random_bytes(reg_vals, param->len_bytes);
2301	KUNIT_EXPECT_EQ(test,
2302			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2303			1);
2304
2305	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2306	KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2307
2308	/* Start the firmware and the cached data should be written to registers */
2309	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2310	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2311
2312	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2313	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2314
2315	/* Control should readback the new data from the control cache */
2316	KUNIT_EXPECT_EQ(test,
2317			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2318			0);
2319	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2320}
2321
2322/*
2323 * Write to a cached control that is not in the currently loaded firmware.
2324 * The value written to the cache should be synced out to the registers
2325 * backing the control the next time the firmware containing the
2326 * control is run.
2327 */
2328static void cs_dsp_ctl_cache_sync_write_not_current_fw(struct kunit *test)
2329{
2330	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2331	struct cs_dsp_test *priv = test->priv;
2332	struct cs_dsp_test_local *local = priv->local;
2333	struct cs_dsp *dsp = priv->dsp;
2334	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2335	int alg_idx = _find_alg_entry(test, param->alg_id);
2336	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2337	unsigned int reg, alg_base_words;
2338	struct cs_dsp_coeff_ctl *ctl;
2339	struct firmware *wmfw;
2340	u32 *reg_vals, *readback;
2341
2342	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2343	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2344
2345	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2346	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2347
2348	/* Create some DSP data to be read into the control cache */
2349	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2350	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2351	reg += (alg_base_words + param->offs_words) *
2352		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2353	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2354
2355	/* Create control pointing to this data */
2356	def.flags = param->flags;
2357	def.mem_type = param->mem_type;
2358	def.offset_dsp_words = param->offs_words;
2359	def.length_bytes = param->len_bytes;
2360
2361	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2362					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2363					      "dummyalg", NULL);
2364	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2365	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2366
2367	/* Power-up DSP but don't start firmware */
2368	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2369	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2370
2371	/* Get the control */
2372	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2373	KUNIT_ASSERT_NOT_NULL(test, ctl);
2374
2375	/* Power-down DSP then power-up with a different firmware */
2376	cs_dsp_power_down(dsp);
2377	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2378	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2379
2380	/* Write new data to the control, it should not be written to the registers */
2381	get_random_bytes(reg_vals, param->len_bytes);
2382	KUNIT_EXPECT_EQ(test,
2383			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2384			1);
2385
2386	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2387	KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2388
2389	/* Power-down DSP then power-up with the original firmware */
2390	cs_dsp_power_down(dsp);
2391	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2392	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2393
2394	/* Start the firmware and the cached data should be written to registers */
2395	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2396	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2397
2398	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2399	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2400
2401	/* Control should readback the new data from the control cache */
2402	KUNIT_EXPECT_EQ(test,
2403			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2404			0);
2405	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2406}
2407
2408/*
2409 * The value in the control cache should be synced out to the registers
2410 * backing the control every time the firmware containing the control
2411 * is run.
2412 */
2413static void cs_dsp_ctl_cache_sync_reapply_every_run(struct kunit *test)
2414{
2415	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2416	struct cs_dsp_test *priv = test->priv;
2417	struct cs_dsp_test_local *local = priv->local;
2418	struct cs_dsp *dsp = priv->dsp;
2419	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2420	int alg_idx = _find_alg_entry(test, param->alg_id);
2421	unsigned int reg, alg_base_words;
2422	struct cs_dsp_coeff_ctl *ctl;
2423	struct firmware *wmfw;
2424	u32 *init_vals, *readback, *ctl_vals;
2425
2426	init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2427	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2428
2429	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2430	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2431
2432	ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2433	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2434
2435	/* Zero-fill the registers backing the control */
2436	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2437	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2438	reg += (alg_base_words + param->offs_words) *
2439		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2440	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2441
2442	/* Create control pointing to this data */
2443	def.flags = param->flags;
2444	def.mem_type = param->mem_type;
2445	def.offset_dsp_words = param->offs_words;
2446	def.length_bytes = param->len_bytes;
2447
2448	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2449					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2450					      "dummyalg", NULL);
2451	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2452	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2453
2454	/* Power-up DSP but don't start firmware */
2455	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2456	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2457
2458	/* Write new data to the control */
2459	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2460	KUNIT_ASSERT_NOT_NULL(test, ctl);
2461
2462	get_random_bytes(ctl_vals, param->len_bytes);
2463	KUNIT_EXPECT_EQ(test,
2464			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2465			1);
2466
2467	/* Start the firmware and the cached data should be written to registers */
2468	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2469	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2470	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2471	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2472
2473	/* Stop the firmware and reset the registers */
2474	kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2475	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2476
2477	/* Start the firmware again and the cached data should be written to registers */
2478	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2479	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2480	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2481	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2482
2483	/* Control should readback the new data from the control cache */
2484	KUNIT_EXPECT_EQ(test,
2485			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2486			0);
2487	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2488}
2489
2490/*
2491 * The value in the control cache should be retained if the same
2492 * firmware is downloaded again. It should be synced out to the
2493 * registers backing the control after the firmware containing the
2494 * control is downloaded again and run.
2495 */
2496static void cs_dsp_ctl_cache_sync_reapply_after_fw_reload(struct kunit *test)
2497{
2498	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2499	struct cs_dsp_test *priv = test->priv;
2500	struct cs_dsp_test_local *local = priv->local;
2501	struct cs_dsp *dsp = priv->dsp;
2502	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2503	int alg_idx = _find_alg_entry(test, param->alg_id);
2504	unsigned int reg, alg_base_words;
2505	struct cs_dsp_coeff_ctl *ctl;
2506	struct firmware *wmfw;
2507	u32 *init_vals, *readback, *ctl_vals;
2508
2509	init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2510	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2511
2512	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2513	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2514
2515	ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2516	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2517
2518	/* Zero-fill the registers backing the control */
2519	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2520	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2521	reg += (alg_base_words + param->offs_words) *
2522		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2523	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2524
2525	/* Create control pointing to this data */
2526	def.flags = param->flags;
2527	def.mem_type = param->mem_type;
2528	def.offset_dsp_words = param->offs_words;
2529	def.length_bytes = param->len_bytes;
2530
2531	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2532					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2533					      "dummyalg", NULL);
2534	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2535	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2536
2537	/* Power-up DSP but don't start firmware */
2538	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2539	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2540
2541	/* Write new data to the control */
2542	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2543	KUNIT_ASSERT_NOT_NULL(test, ctl);
2544
2545	get_random_bytes(ctl_vals, param->len_bytes);
2546	KUNIT_EXPECT_EQ(test,
2547			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2548			1);
2549
2550	/* Start the firmware and the cached data should be written to registers */
2551	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2552	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2553	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2554	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2555
2556	/* Stop the firmware and power-down the DSP */
2557	kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2558	cs_dsp_power_down(dsp);
2559
2560	/* Reset the registers */
2561	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2562
2563	/* Download the firmware again, the cache content should not change */
2564	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2565
2566	/* Start the firmware and the cached data should be written to registers */
2567	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2568	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2569	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2570	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2571
2572	/* Control should readback the new data from the control cache */
2573	KUNIT_EXPECT_EQ(test,
2574			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2575			0);
2576	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2577}
2578
2579/*
2580 * The value in the control cache should be retained after a different
2581 * firmware is downloaded.
2582 * When the firmware containing the control is downloaded and run
2583 * the value in the control cache should be synced out to the registers
2584 * backing the control.
2585 */
2586static void cs_dsp_ctl_cache_sync_reapply_after_fw_swap(struct kunit *test)
2587{
2588	const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2589	struct cs_dsp_test *priv = test->priv;
2590	struct cs_dsp_test_local *local = priv->local;
2591	struct cs_dsp *dsp = priv->dsp;
2592	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2593	int alg_idx = _find_alg_entry(test, param->alg_id);
2594	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2595	unsigned int reg, alg_base_words;
2596	struct cs_dsp_coeff_ctl *ctl;
2597	struct firmware *wmfw;
2598	u32 *init_vals, *readback, *ctl_vals;
2599
2600	init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2601	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2602
2603	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2604	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2605
2606	ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2607	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2608
2609	/* Zero-fill the registers backing the control */
2610	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2611	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2612	reg += (alg_base_words + param->offs_words) *
2613		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2614	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2615
2616	/* Create control pointing to this data */
2617	def.flags = param->flags;
2618	def.mem_type = param->mem_type;
2619	def.offset_dsp_words = param->offs_words;
2620	def.length_bytes = param->len_bytes;
2621
2622	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2623					      cs_dsp_ctl_cache_test_algs[alg_idx].id,
2624					      "dummyalg", NULL);
2625	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2626	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2627
2628	/* Power-up DSP but don't start firmware */
2629	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2630	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2631
2632	/* Write new data to the control */
2633	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2634	KUNIT_ASSERT_NOT_NULL(test, ctl);
2635
2636	get_random_bytes(ctl_vals, param->len_bytes);
2637	KUNIT_EXPECT_EQ(test,
2638			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2639			1);
2640
2641	/* Start the firmware and the cached data should be written to registers */
2642	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2643	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2644	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2645	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2646
2647	/* Stop the firmware and power-down the DSP */
2648	kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2649	cs_dsp_power_down(dsp);
2650
2651	/* Reset the registers */
2652	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2653
2654	/* Download and run a different firmware */
2655	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2656	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2657	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2658	cs_dsp_power_down(dsp);
2659
2660	/* Reset the registers */
2661	regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2662
2663	/* Download the original firmware again */
2664	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2665	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2666	KUNIT_EXPECT_TRUE(test, ctl->set);
2667
2668	/* Start the firmware and the cached data should be written to registers */
2669	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2670	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2671	KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2672	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2673
2674	/* Control should readback the new data from the control cache */
2675	KUNIT_EXPECT_EQ(test,
2676			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2677			0);
2678	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2679}
2680
2681static int cs_dsp_ctl_cache_test_common_init(struct kunit *test, struct cs_dsp *dsp,
2682					     int wmfw_version)
2683{
2684	struct cs_dsp_test *priv;
2685	struct cs_dsp_test_local *local;
2686	struct device *test_dev;
2687	int ret;
2688
2689	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2690	if (!priv)
2691		return -ENOMEM;
2692
2693	local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2694	if (!local)
2695		return -ENOMEM;
2696
2697	priv->test = test;
2698	priv->dsp = dsp;
2699	test->priv = priv;
2700	priv->local = local;
2701	priv->local->wmfw_version = wmfw_version;
2702
2703	/* Create dummy struct device */
2704	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2705	if (IS_ERR(test_dev))
2706		return PTR_ERR(test_dev);
2707
2708	dsp->dev = get_device(test_dev);
2709	if (!dsp->dev)
2710		return -ENODEV;
2711
2712	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2713	if (ret)
2714		return ret;
2715
2716	dev_set_drvdata(dsp->dev, priv);
2717
2718	/* Allocate regmap */
2719	ret = cs_dsp_mock_regmap_init(priv);
2720	if (ret)
2721		return ret;
2722
2723	/*
2724	 * There must always be a XM header with at least 1 algorithm, so create
2725	 * a dummy one that tests can use and extract it to a data blob.
2726	 */
2727	local->xm_header = cs_dsp_create_mock_xm_header(priv,
2728							cs_dsp_ctl_cache_test_algs,
2729							ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
2730	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
2731
2732	/* Create wmfw builder */
2733	local->wmfw_builder = _create_dummy_wmfw(test);
2734
2735	/* Init cs_dsp */
2736	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2737	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2738
2739	switch (dsp->type) {
2740	case WMFW_ADSP2:
2741		ret = cs_dsp_adsp2_init(dsp);
2742		break;
2743	case WMFW_HALO:
2744		ret = cs_dsp_halo_init(dsp);
2745		break;
2746	default:
2747		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2748		return -EINVAL;
2749	}
2750
2751	if (ret)
2752		return ret;
2753
2754	/* Automatically call cs_dsp_remove() when test case ends */
2755	return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2756}
2757
2758static int cs_dsp_ctl_cache_test_halo_init(struct kunit *test)
2759{
2760	struct cs_dsp *dsp;
2761
2762	/* Fill in cs_dsp and initialize */
2763	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2764	if (!dsp)
2765		return -ENOMEM;
2766
2767	dsp->num = 1;
2768	dsp->type = WMFW_HALO;
2769	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2770	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2771	dsp->base = cs_dsp_mock_halo_core_base;
2772	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2773
2774	return cs_dsp_ctl_cache_test_common_init(test, dsp, 3);
2775}
2776
2777static int cs_dsp_ctl_cache_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
2778{
2779	struct cs_dsp *dsp;
2780
2781	/* Fill in cs_dsp and initialize */
2782	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2783	if (!dsp)
2784		return -ENOMEM;
2785
2786	dsp->num = 1;
2787	dsp->type = WMFW_ADSP2;
2788	dsp->rev = 1;
2789	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2790	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2791	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2792
2793	return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver);
2794}
2795
2796static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init(struct kunit *test)
2797{
2798	return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 1);
2799}
2800
2801static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init(struct kunit *test)
2802{
2803	return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 2);
2804}
2805
2806static int cs_dsp_ctl_cache_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
2807{
2808	struct cs_dsp *dsp;
2809
2810	/* Fill in cs_dsp and initialize */
2811	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2812	if (!dsp)
2813		return -ENOMEM;
2814
2815	dsp->num = 1;
2816	dsp->type = WMFW_ADSP2;
2817	dsp->rev = 0;
2818	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2819	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2820	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2821
2822	return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver);
2823}
2824
2825static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init(struct kunit *test)
2826{
2827	return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 1);
2828}
2829
2830static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init(struct kunit *test)
2831{
2832	return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 2);
2833}
2834
2835static void cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_cache_test_param *param,
2836				      char *desc)
2837{
2838	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg:%#x %s@%u len:%u flags:%#x",
2839		 param->alg_id, cs_dsp_mem_region_name(param->mem_type),
2840		 param->offs_words, param->len_bytes, param->flags);
2841}
2842
2843/* All parameters populated, with various lengths */
2844static const struct cs_dsp_ctl_cache_test_param all_pop_varying_len_cases[] = {
2845	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2846	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 8 },
2847	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 12 },
2848	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 16 },
2849	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 48 },
2850	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 100 },
2851	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512 },
2852	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 1000 },
2853};
2854KUNIT_ARRAY_PARAM(all_pop_varying_len, all_pop_varying_len_cases,
2855		  cs_dsp_ctl_all_param_desc);
2856
2857/* All parameters populated, with various offsets */
2858static const struct cs_dsp_ctl_cache_test_param all_pop_varying_offset_cases[] = {
2859	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 0,   .len_bytes = 4 },
2860	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1,   .len_bytes = 4 },
2861	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 2,   .len_bytes = 4 },
2862	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 3,   .len_bytes = 4 },
2863	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 8,   .len_bytes = 4 },
2864	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 10,  .len_bytes = 4 },
2865	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 128, .len_bytes = 4 },
2866	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 180, .len_bytes = 4 },
2867};
2868KUNIT_ARRAY_PARAM(all_pop_varying_offset, all_pop_varying_offset_cases,
2869		  cs_dsp_ctl_all_param_desc);
2870
2871/* All parameters populated, with various X and Y memory regions */
2872static const struct cs_dsp_ctl_cache_test_param all_pop_varying_xy_cases[] = {
2873	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_XM, .offs_words = 1, .len_bytes = 4 },
2874	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2875};
2876KUNIT_ARRAY_PARAM(all_pop_varying_xy, all_pop_varying_xy_cases,
2877		  cs_dsp_ctl_all_param_desc);
2878
2879/* All parameters populated, using ZM */
2880static const struct cs_dsp_ctl_cache_test_param all_pop_z_cases[] = {
2881	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_ZM, .offs_words = 1, .len_bytes = 4 },
2882};
2883KUNIT_ARRAY_PARAM(all_pop_z, all_pop_z_cases, cs_dsp_ctl_all_param_desc);
2884
2885/* All parameters populated, with various algorithm ids */
2886static const struct cs_dsp_ctl_cache_test_param all_pop_varying_alg_cases[] = {
2887	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2888	{ .alg_id = 0xb,      .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2889	{ .alg_id = 0x9f1234, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2890	{ .alg_id = 0xff00ff, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2891};
2892KUNIT_ARRAY_PARAM(all_pop_varying_alg, all_pop_varying_alg_cases,
2893		  cs_dsp_ctl_all_param_desc);
2894
2895/*
2896 * All parameters populated, with all combinations of flags for a
2897 * non-volatile readable control
2898 */
2899static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_flags_cases[] = {
2900	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2901	  .flags = 0
2902	},
2903	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2904	  .flags = WMFW_CTL_FLAG_READABLE,
2905	},
2906	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2907	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2908	},
2909	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2910	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2911	},
2912	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2913	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2914	},
2915};
2916KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_flags,
2917		  all_pop_nonvol_readable_flags_cases,
2918		  cs_dsp_ctl_all_param_desc);
2919
2920/*
2921 * All parameters populated, with all combinations of flags for a
2922 * non-volatile readable control, except flags==0
2923 */
2924static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_nonzero_flags_cases[] = {
2925	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2926	  .flags = WMFW_CTL_FLAG_READABLE,
2927	},
2928	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2929	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2930	},
2931	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2932	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2933	},
2934	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2935	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2936	},
2937};
2938KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_nonzero_flags,
2939		  all_pop_nonvol_readable_nonzero_flags_cases,
2940		  cs_dsp_ctl_all_param_desc);
2941
2942/*
2943 * All parameters populated, with all combinations of flags for a
2944 * non-volatile writeable control
2945 */
2946static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_writeable_flags_cases[] = {
2947	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2948	  .flags = 0
2949	},
2950	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2951	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2952	},
2953	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2954	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2955	},
2956	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2957	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2958	},
2959	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2960	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2961	},
2962};
2963KUNIT_ARRAY_PARAM(all_pop_nonvol_writeable_flags,
2964		  all_pop_nonvol_writeable_flags_cases,
2965		  cs_dsp_ctl_all_param_desc);
2966
2967/*
2968 * All parameters populated, with all combinations of flags for a
2969 * non-volatile write-only control of varying lengths
2970 */
2971static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_write_only_length_cases[] = {
2972	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2973	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2974	},
2975	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512,
2976	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2977	},
2978	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2979	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2980	},
2981	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512,
2982	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2983	},
2984};
2985KUNIT_ARRAY_PARAM(all_pop_nonvol_write_only_length,
2986		  all_pop_nonvol_write_only_length_cases,
2987		  cs_dsp_ctl_all_param_desc);
2988
2989static struct kunit_case cs_dsp_ctl_cache_test_cases_v1[] = {
2990	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
2991	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
2992	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
2993	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params),
2994	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
2995	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
2996
2997	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
2998			 all_pop_nonvol_write_only_length_gen_params),
2999
3000	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3001	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3002	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3003	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3004
3005	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3006			 all_pop_nonvol_readable_flags_gen_params),
3007	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3008			 all_pop_nonvol_readable_flags_gen_params),
3009	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3010			 all_pop_nonvol_readable_flags_gen_params),
3011	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3012			 all_pop_nonvol_readable_flags_gen_params),
3013	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3014			 all_pop_nonvol_readable_flags_gen_params),
3015	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3016			 all_pop_nonvol_readable_flags_gen_params),
3017	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3018			 all_pop_nonvol_readable_nonzero_flags_gen_params),
3019	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags,
3020			 all_pop_varying_len_gen_params),
3021
3022	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3023	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3024	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3025	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params),
3026	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3027	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3028
3029	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3030			 all_pop_varying_len_gen_params),
3031	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3032			 all_pop_varying_offset_gen_params),
3033	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3034			 all_pop_varying_xy_gen_params),
3035	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3036			 all_pop_z_gen_params),
3037	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3038			 all_pop_varying_alg_gen_params),
3039	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3040			 all_pop_nonvol_writeable_flags_gen_params),
3041
3042	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3043			 all_pop_nonvol_writeable_flags_gen_params),
3044	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3045			 all_pop_nonvol_writeable_flags_gen_params),
3046	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3047			 all_pop_nonvol_writeable_flags_gen_params),
3048	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3049			 all_pop_nonvol_writeable_flags_gen_params),
3050	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3051			 all_pop_nonvol_writeable_flags_gen_params),
3052	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3053			 all_pop_nonvol_writeable_flags_gen_params),
3054	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3055			 all_pop_nonvol_writeable_flags_gen_params),
3056
3057	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3058			 all_pop_nonvol_writeable_flags_gen_params),
3059	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3060			 all_pop_nonvol_writeable_flags_gen_params),
3061	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3062			 all_pop_nonvol_writeable_flags_gen_params),
3063	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3064			 all_pop_nonvol_writeable_flags_gen_params),
3065	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3066			 all_pop_nonvol_writeable_flags_gen_params),
3067	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3068			 all_pop_nonvol_writeable_flags_gen_params),
3069	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3070			 all_pop_nonvol_writeable_flags_gen_params),
3071
3072	{ } /* terminator */
3073};
3074
3075static struct kunit_case cs_dsp_ctl_cache_test_cases_v2[] = {
3076	KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc),
3077
3078	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
3079	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
3080	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
3081	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params),
3082	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
3083	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
3084
3085	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
3086			 all_pop_nonvol_write_only_length_gen_params),
3087
3088	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3089	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3090	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3091	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3092	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets),
3093
3094	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3095			 all_pop_nonvol_readable_flags_gen_params),
3096	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3097			 all_pop_nonvol_readable_flags_gen_params),
3098	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3099			 all_pop_nonvol_readable_flags_gen_params),
3100	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3101			 all_pop_nonvol_readable_flags_gen_params),
3102	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3103			 all_pop_nonvol_readable_flags_gen_params),
3104	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3105			 all_pop_nonvol_readable_flags_gen_params),
3106	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3107			 all_pop_nonvol_readable_nonzero_flags_gen_params),
3108	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags,
3109			 all_pop_varying_len_gen_params),
3110
3111	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3112	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3113	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3114	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params),
3115	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3116	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3117
3118	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3119			 all_pop_varying_len_gen_params),
3120	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3121			 all_pop_varying_offset_gen_params),
3122	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3123			 all_pop_varying_xy_gen_params),
3124	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3125			 all_pop_z_gen_params),
3126	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3127			 all_pop_varying_alg_gen_params),
3128	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3129			 all_pop_nonvol_writeable_flags_gen_params),
3130
3131	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3132			 all_pop_nonvol_writeable_flags_gen_params),
3133	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3134			 all_pop_nonvol_writeable_flags_gen_params),
3135	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3136			 all_pop_nonvol_writeable_flags_gen_params),
3137	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3138			 all_pop_nonvol_writeable_flags_gen_params),
3139	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3140			 all_pop_nonvol_writeable_flags_gen_params),
3141	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3142			 all_pop_nonvol_writeable_flags_gen_params),
3143	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3144			 all_pop_nonvol_writeable_flags_gen_params),
3145
3146	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3147			 all_pop_nonvol_writeable_flags_gen_params),
3148	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3149			 all_pop_nonvol_writeable_flags_gen_params),
3150	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3151			 all_pop_nonvol_writeable_flags_gen_params),
3152	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3153			 all_pop_nonvol_writeable_flags_gen_params),
3154	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3155			 all_pop_nonvol_writeable_flags_gen_params),
3156	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3157			 all_pop_nonvol_writeable_flags_gen_params),
3158	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3159			 all_pop_nonvol_writeable_flags_gen_params),
3160
3161	{ } /* terminator */
3162};
3163
3164static struct kunit_case cs_dsp_ctl_cache_test_cases_v3[] = {
3165	KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc),
3166
3167	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
3168	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
3169	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
3170	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
3171	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
3172
3173	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
3174			 all_pop_nonvol_write_only_length_gen_params),
3175
3176	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3177	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3178	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3179	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3180	KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets),
3181
3182	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3183			 all_pop_nonvol_readable_flags_gen_params),
3184	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3185			 all_pop_nonvol_readable_flags_gen_params),
3186	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3187			 all_pop_nonvol_readable_flags_gen_params),
3188	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3189			 all_pop_nonvol_readable_flags_gen_params),
3190	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3191			 all_pop_nonvol_readable_flags_gen_params),
3192	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3193			 all_pop_nonvol_readable_flags_gen_params),
3194	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3195			 all_pop_nonvol_readable_nonzero_flags_gen_params),
3196
3197	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3198	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3199	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3200	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3201	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3202
3203	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3204			 all_pop_varying_len_gen_params),
3205	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3206			 all_pop_varying_offset_gen_params),
3207	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3208			 all_pop_varying_xy_gen_params),
3209	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3210			 all_pop_varying_alg_gen_params),
3211	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3212			 all_pop_nonvol_writeable_flags_gen_params),
3213
3214	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3215			 all_pop_nonvol_writeable_flags_gen_params),
3216	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3217			 all_pop_nonvol_writeable_flags_gen_params),
3218	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3219			 all_pop_nonvol_writeable_flags_gen_params),
3220	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3221			 all_pop_nonvol_writeable_flags_gen_params),
3222	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3223			 all_pop_nonvol_writeable_flags_gen_params),
3224	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3225			 all_pop_nonvol_writeable_flags_gen_params),
3226	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3227			 all_pop_nonvol_writeable_flags_gen_params),
3228
3229	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3230			 all_pop_nonvol_writeable_flags_gen_params),
3231	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3232			 all_pop_nonvol_writeable_flags_gen_params),
3233	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3234			 all_pop_nonvol_writeable_flags_gen_params),
3235	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3236			 all_pop_nonvol_writeable_flags_gen_params),
3237	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3238			 all_pop_nonvol_writeable_flags_gen_params),
3239	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3240			 all_pop_nonvol_writeable_flags_gen_params),
3241	KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3242			 all_pop_nonvol_writeable_flags_gen_params),
3243
3244	{ } /* terminator */
3245};
3246
3247static struct kunit_suite cs_dsp_ctl_cache_test_halo = {
3248	.name = "cs_dsp_ctl_cache_wmfwV3_halo",
3249	.init = cs_dsp_ctl_cache_test_halo_init,
3250	.test_cases = cs_dsp_ctl_cache_test_cases_v3,
3251};
3252
3253static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1 = {
3254	.name = "cs_dsp_ctl_cache_wmfwV1_adsp2_32bit",
3255	.init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init,
3256	.test_cases = cs_dsp_ctl_cache_test_cases_v1,
3257};
3258
3259static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2 = {
3260	.name = "cs_dsp_ctl_cache_wmfwV2_adsp2_32bit",
3261	.init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init,
3262	.test_cases = cs_dsp_ctl_cache_test_cases_v2,
3263};
3264
3265static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1 = {
3266	.name = "cs_dsp_ctl_cache_wmfwV1_adsp2_16bit",
3267	.init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init,
3268	.test_cases = cs_dsp_ctl_cache_test_cases_v1,
3269};
3270
3271static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2 = {
3272	.name = "cs_dsp_ctl_cache_wmfwV2_adsp2_16bit",
3273	.init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init,
3274	.test_cases = cs_dsp_ctl_cache_test_cases_v2,
3275};
3276
3277kunit_test_suites(&cs_dsp_ctl_cache_test_halo,
3278		  &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1,
3279		  &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2,
3280		  &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1,
3281		  &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2);
~/ Read-only file preview.