File Index
Files and directories
Sign in
FILE

cs_dsp_test_control_rw.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/cirrus/test/cs_dsp_test_control_rw.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_rw_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_rw_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 int _find_alg_entry(struct kunit *test, unsigned int alg_id)
  90{
  91	int i;
  92
  93	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_rw_test_algs); ++i) {
  94		if (cs_dsp_ctl_rw_test_algs[i].id == alg_id)
  95			break;
  96	}
  97
  98	KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(cs_dsp_ctl_rw_test_algs));
  99
 100	return i;
 101}
 102
 103static int _get_alg_mem_base_words(struct kunit *test, int alg_index, int mem_type)
 104{
 105	switch (mem_type) {
 106	case WMFW_ADSP2_XM:
 107		return cs_dsp_ctl_rw_test_algs[alg_index].xm_base_words;
 108	case WMFW_ADSP2_YM:
 109		return cs_dsp_ctl_rw_test_algs[alg_index].ym_base_words;
 110	case WMFW_ADSP2_ZM:
 111		return cs_dsp_ctl_rw_test_algs[alg_index].zm_base_words;
 112	default:
 113		KUNIT_FAIL(test, "Bug in test: illegal memory type %d\n", mem_type);
 114		return 0;
 115	}
 116}
 117
 118static struct cs_dsp_mock_wmfw_builder *_create_dummy_wmfw(struct kunit *test)
 119{
 120	struct cs_dsp_test *priv = test->priv;
 121	struct cs_dsp_test_local *local = priv->local;
 122	struct cs_dsp_mock_wmfw_builder *builder;
 123
 124	builder = cs_dsp_mock_wmfw_init(priv, local->wmfw_version);
 125	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder);
 126
 127	/* Init an XM header */
 128	cs_dsp_mock_wmfw_add_data_block(builder,
 129					WMFW_ADSP2_XM, 0,
 130					local->xm_header->blob_data,
 131					local->xm_header->blob_size_bytes);
 132
 133	return builder;
 134}
 135
 136/*
 137 * Write to a control while the firmware is running.
 138 * This should write to the underlying registers.
 139 */
 140static void cs_dsp_ctl_write_running(struct kunit *test)
 141{
 142	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 143	struct cs_dsp_test *priv = test->priv;
 144	struct cs_dsp_test_local *local = priv->local;
 145	struct cs_dsp *dsp = priv->dsp;
 146	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 147	int alg_idx = _find_alg_entry(test, param->alg_id);
 148	unsigned int reg, alg_base_words;
 149	struct cs_dsp_coeff_ctl *ctl;
 150	struct firmware *wmfw;
 151	u32 *reg_vals, *readback;
 152
 153	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 154	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 155
 156	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 157	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 158
 159	/* Create some initial register content */
 160	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 161	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 162	reg += (alg_base_words + param->offs_words) *
 163		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 164	memset(reg_vals, 0, param->len_bytes);
 165	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 166
 167	/* Create control pointing to this data */
 168	def.flags = param->flags;
 169	def.mem_type = param->mem_type;
 170	def.offset_dsp_words = param->offs_words;
 171	def.length_bytes = param->len_bytes;
 172
 173	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 174					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 175					      "dummyalg", NULL);
 176	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 177	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 178
 179	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 180	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 181
 182	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 183	KUNIT_ASSERT_NOT_NULL(test, ctl);
 184
 185	/* Start the firmware and add an action to stop it during cleanup */
 186	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 187	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
 188
 189	/*
 190	 * Write new data to the control, it should be written to the registers
 191	 * and cs_dsp_coeff_lock_and_write_ctrl() should return 1 to indicate
 192	 * that the control content changed.
 193	 */
 194	get_random_bytes(reg_vals, param->len_bytes);
 195	KUNIT_EXPECT_EQ(test,
 196			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
 197			1);
 198	KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
 199	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
 200
 201	/* Drop expected writes and the regmap cache should be clean */
 202	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 203	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 204	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 205}
 206
 207/*
 208 * Read from a volatile control while the firmware is running.
 209 * This should return the current state of the underlying registers.
 210 */
 211static void cs_dsp_ctl_read_volatile_running(struct kunit *test)
 212{
 213	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 214	struct cs_dsp_test *priv = test->priv;
 215	struct cs_dsp_test_local *local = priv->local;
 216	struct cs_dsp *dsp = priv->dsp;
 217	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 218	int alg_idx = _find_alg_entry(test, param->alg_id);
 219	unsigned int reg, alg_base_words;
 220	struct cs_dsp_coeff_ctl *ctl;
 221	struct firmware *wmfw;
 222	u32 *reg_vals, *readback;
 223
 224	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 225	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 226
 227	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 228	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 229
 230	/* Create some initial register content */
 231	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 232	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 233	reg += (alg_base_words + param->offs_words) *
 234		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 235	memset(reg_vals, 0, param->len_bytes);
 236	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 237
 238	/* Create control pointing to this data */
 239	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 240	def.mem_type = param->mem_type;
 241	def.offset_dsp_words = param->offs_words;
 242	def.length_bytes = param->len_bytes;
 243
 244	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 245					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 246					      "dummyalg", NULL);
 247	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 248	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 249
 250	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 251	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 252
 253	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 254	KUNIT_ASSERT_NOT_NULL(test, ctl);
 255
 256	/* Start the firmware and add an action to stop it during cleanup */
 257	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 258	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
 259
 260	/* Read the control, it should return the current register content */
 261	KUNIT_EXPECT_EQ(test,
 262			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
 263			0);
 264	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
 265
 266	/*
 267	 * Change the register content and read the control, it should return
 268	 * the new register content
 269	 */
 270	get_random_bytes(reg_vals, param->len_bytes);
 271	KUNIT_ASSERT_EQ(test, regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes), 0);
 272	KUNIT_EXPECT_EQ(test,
 273			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
 274			0);
 275	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
 276}
 277
 278/*
 279 * Read from a volatile control before the firmware is started.
 280 * This should return an error.
 281 */
 282static void cs_dsp_ctl_read_volatile_not_started(struct kunit *test)
 283{
 284	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 285	struct cs_dsp_test *priv = test->priv;
 286	struct cs_dsp_test_local *local = priv->local;
 287	struct cs_dsp *dsp = priv->dsp;
 288	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 289	int alg_idx = _find_alg_entry(test, param->alg_id);
 290	unsigned int reg, alg_base_words;
 291	struct cs_dsp_coeff_ctl *ctl;
 292	struct firmware *wmfw;
 293	u32 *reg_vals;
 294
 295	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 296	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 297
 298	/* Create some initial register content */
 299	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 300	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 301	reg += (alg_base_words + param->offs_words) *
 302		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 303	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 304
 305	/* Create control pointing to this data */
 306	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 307	def.mem_type = param->mem_type;
 308	def.offset_dsp_words = param->offs_words;
 309	def.length_bytes = param->len_bytes;
 310
 311	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 312					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 313					      "dummyalg", NULL);
 314	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 315	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 316
 317	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 318	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 319
 320	/* Read the control, it should return an error */
 321	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 322	KUNIT_ASSERT_NOT_NULL(test, ctl);
 323	KUNIT_EXPECT_LT(test,
 324			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
 325			0);
 326}
 327
 328/*
 329 * Read from a volatile control after the firmware has stopped.
 330 * This should return an error.
 331 */
 332static void cs_dsp_ctl_read_volatile_stopped(struct kunit *test)
 333{
 334	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 335	struct cs_dsp_test *priv = test->priv;
 336	struct cs_dsp_test_local *local = priv->local;
 337	struct cs_dsp *dsp = priv->dsp;
 338	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 339	int alg_idx = _find_alg_entry(test, param->alg_id);
 340	unsigned int reg, alg_base_words;
 341	struct cs_dsp_coeff_ctl *ctl;
 342	struct firmware *wmfw;
 343	u32 *reg_vals;
 344
 345	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 346	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 347
 348	/* Create some initial register content */
 349	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 350	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 351	reg += (alg_base_words + param->offs_words) *
 352		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 353	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 354
 355	/* Create control pointing to this data */
 356	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 357	def.mem_type = param->mem_type;
 358	def.offset_dsp_words = param->offs_words;
 359	def.length_bytes = param->len_bytes;
 360
 361	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 362					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 363					      "dummyalg", NULL);
 364	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 365	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 366
 367	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 368	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 369
 370	/* Start and stop the firmware */
 371	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 372	cs_dsp_stop(dsp);
 373
 374	/* Read the control, it should return an error */
 375	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 376	KUNIT_ASSERT_NOT_NULL(test, ctl);
 377	KUNIT_EXPECT_LT(test,
 378			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
 379			0);
 380}
 381
 382/*
 383 * Read from a volatile control after the DSP has been powered down.
 384 * This should return an error.
 385 */
 386static void cs_dsp_ctl_read_volatile_stopped_powered_down(struct kunit *test)
 387{
 388	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 389	struct cs_dsp_test *priv = test->priv;
 390	struct cs_dsp_test_local *local = priv->local;
 391	struct cs_dsp *dsp = priv->dsp;
 392	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 393	int alg_idx = _find_alg_entry(test, param->alg_id);
 394	unsigned int reg, alg_base_words;
 395	struct cs_dsp_coeff_ctl *ctl;
 396	struct firmware *wmfw;
 397	u32 *reg_vals;
 398
 399	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 400	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 401
 402	/* Create some initial register content */
 403	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 404	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 405	reg += (alg_base_words + param->offs_words) *
 406		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 407	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 408
 409	/* Create control pointing to this data */
 410	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 411	def.mem_type = param->mem_type;
 412	def.offset_dsp_words = param->offs_words;
 413	def.length_bytes = param->len_bytes;
 414
 415	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 416					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 417					      "dummyalg", NULL);
 418	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 419	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 420
 421	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 422	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 423
 424	/* Start and stop the firmware then power down */
 425	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 426	cs_dsp_stop(dsp);
 427	cs_dsp_power_down(dsp);
 428
 429	/* Read the control, it should return an error */
 430	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 431	KUNIT_ASSERT_NOT_NULL(test, ctl);
 432	KUNIT_EXPECT_LT(test,
 433			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
 434			0);
 435}
 436
 437/*
 438 * Read from a volatile control when a different firmware is currently
 439 * loaded into the DSP.
 440 * Should return an error.
 441 */
 442static void cs_dsp_ctl_read_volatile_not_current_loaded_fw(struct kunit *test)
 443{
 444	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 445	struct cs_dsp_test *priv = test->priv;
 446	struct cs_dsp_test_local *local = priv->local;
 447	struct cs_dsp *dsp = priv->dsp;
 448	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 449	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
 450	int alg_idx = _find_alg_entry(test, param->alg_id);
 451	unsigned int reg, alg_base_words;
 452	struct cs_dsp_coeff_ctl *ctl;
 453	struct firmware *wmfw;
 454	u32 *reg_vals;
 455
 456	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 457	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 458
 459	/* Create some DSP data to be read into the control cache */
 460	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 461	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 462	reg += (alg_base_words + param->offs_words) *
 463		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 464	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 465
 466	/* Create control pointing to this data */
 467	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 468	def.mem_type = param->mem_type;
 469	def.offset_dsp_words = param->offs_words;
 470	def.length_bytes = param->len_bytes;
 471
 472	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 473					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 474					      "dummyalg", NULL);
 475	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 476	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 477
 478	/* Power-up DSP */
 479	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 480	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 481
 482	/* Power-down DSP then power-up with a different firmware */
 483	cs_dsp_power_down(dsp);
 484	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
 485	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
 486
 487	/* Read the control, it should return an error */
 488	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 489	KUNIT_ASSERT_NOT_NULL(test, ctl);
 490	KUNIT_EXPECT_LT(test,
 491			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
 492			0);
 493}
 494
 495/*
 496 * Read from a volatile control when a different firmware is currently
 497 * running.
 498 * Should return an error.
 499 */
 500static void cs_dsp_ctl_read_volatile_not_current_running_fw(struct kunit *test)
 501{
 502	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 503	struct cs_dsp_test *priv = test->priv;
 504	struct cs_dsp_test_local *local = priv->local;
 505	struct cs_dsp *dsp = priv->dsp;
 506	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 507	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
 508	int alg_idx = _find_alg_entry(test, param->alg_id);
 509	unsigned int reg, alg_base_words;
 510	struct cs_dsp_coeff_ctl *ctl;
 511	struct firmware *wmfw;
 512	u32 *reg_vals;
 513
 514	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 515	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 516
 517	/* Create some DSP data to be read into the control cache */
 518	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 519	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 520	reg += (alg_base_words + param->offs_words) *
 521		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 522	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 523
 524	/* Create control pointing to this data */
 525	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 526	def.mem_type = param->mem_type;
 527	def.offset_dsp_words = param->offs_words;
 528	def.length_bytes = param->len_bytes;
 529
 530	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 531					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 532					      "dummyalg", NULL);
 533	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 534	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 535
 536	/* Power-up DSP */
 537	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 538	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 539
 540	/* Power-down DSP then power-up with a different firmware */
 541	cs_dsp_power_down(dsp);
 542	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
 543	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
 544
 545	/* Start the firmware and add an action to stop it during cleanup */
 546	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 547	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
 548
 549	/* Read the control, it should return an error */
 550	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 551	KUNIT_ASSERT_NOT_NULL(test, ctl);
 552	KUNIT_EXPECT_LT(test,
 553			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
 554			0);
 555}
 556
 557/*
 558 * Write to a volatile control before the firmware is started.
 559 * This should return an error.
 560 */
 561static void cs_dsp_ctl_write_volatile_not_started(struct kunit *test)
 562{
 563	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 564	struct cs_dsp_test *priv = test->priv;
 565	struct cs_dsp_test_local *local = priv->local;
 566	struct cs_dsp *dsp = priv->dsp;
 567	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 568	int alg_idx = _find_alg_entry(test, param->alg_id);
 569	unsigned int reg, alg_base_words;
 570	struct cs_dsp_coeff_ctl *ctl;
 571	struct firmware *wmfw;
 572	u32 *reg_vals;
 573
 574	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 575	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 576
 577	/* Create some initial register content */
 578	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 579	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 580	reg += (alg_base_words + param->offs_words) *
 581		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 582	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 583
 584	/* Create control pointing to this data */
 585	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 586	def.mem_type = param->mem_type;
 587	def.offset_dsp_words = param->offs_words;
 588	def.length_bytes = param->len_bytes;
 589
 590	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 591					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 592					      "dummyalg", NULL);
 593	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 594	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 595
 596	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 597	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 598
 599	/* Drop expected writes and the regmap cache should be clean */
 600	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 601	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 602
 603	/* Write the control, it should return an error */
 604	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 605	KUNIT_ASSERT_NOT_NULL(test, ctl);
 606	KUNIT_EXPECT_LT(test,
 607			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
 608			0);
 609
 610	/* Should not have been any writes to registers */
 611	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 612}
 613
 614/*
 615 * Write to a volatile control after the firmware has stopped.
 616 * This should return an error.
 617 */
 618static void cs_dsp_ctl_write_volatile_stopped(struct kunit *test)
 619{
 620	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 621	struct cs_dsp_test *priv = test->priv;
 622	struct cs_dsp_test_local *local = priv->local;
 623	struct cs_dsp *dsp = priv->dsp;
 624	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 625	int alg_idx = _find_alg_entry(test, param->alg_id);
 626	unsigned int reg, alg_base_words;
 627	struct cs_dsp_coeff_ctl *ctl;
 628	struct firmware *wmfw;
 629	u32 *reg_vals;
 630
 631	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 632	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 633
 634	/* Create some initial register content */
 635	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 636	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 637	reg += (alg_base_words + param->offs_words) *
 638		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 639	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 640
 641	/* Create control pointing to this data */
 642	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 643	def.mem_type = param->mem_type;
 644	def.offset_dsp_words = param->offs_words;
 645	def.length_bytes = param->len_bytes;
 646
 647	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 648					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 649					      "dummyalg", NULL);
 650	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 651	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 652
 653	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 654	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 655
 656	/* Start and stop the firmware */
 657	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 658	cs_dsp_stop(dsp);
 659
 660	/* Drop expected writes and the regmap cache should be clean */
 661	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 662	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 663
 664	/* Write the control, it should return an error */
 665	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 666	KUNIT_ASSERT_NOT_NULL(test, ctl);
 667	KUNIT_EXPECT_LT(test,
 668			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
 669			0);
 670
 671	/* Should not have been any writes to registers */
 672	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 673}
 674
 675/*
 676 * Write to a volatile control after the DSP has been powered down.
 677 * This should return an error.
 678 */
 679static void cs_dsp_ctl_write_volatile_stopped_powered_down(struct kunit *test)
 680{
 681	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 682	struct cs_dsp_test *priv = test->priv;
 683	struct cs_dsp_test_local *local = priv->local;
 684	struct cs_dsp *dsp = priv->dsp;
 685	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 686	int alg_idx = _find_alg_entry(test, param->alg_id);
 687	unsigned int reg, alg_base_words;
 688	struct cs_dsp_coeff_ctl *ctl;
 689	struct firmware *wmfw;
 690	u32 *reg_vals;
 691
 692	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
 693	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 694
 695	/* Create some initial register content */
 696	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 697	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 698	reg += (alg_base_words + param->offs_words) *
 699		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 700	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 701
 702	/* Create control pointing to this data */
 703	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 704	def.mem_type = param->mem_type;
 705	def.offset_dsp_words = param->offs_words;
 706	def.length_bytes = param->len_bytes;
 707
 708	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 709					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 710					      "dummyalg", NULL);
 711	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 712	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 713
 714	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 715	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 716
 717	/* Start and stop the firmware then power down */
 718	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 719	cs_dsp_stop(dsp);
 720	cs_dsp_power_down(dsp);
 721
 722	/* Drop expected writes and the regmap cache should be clean */
 723	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 724	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 725
 726	/* Write the control, it should return an error */
 727	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 728	KUNIT_ASSERT_NOT_NULL(test, ctl);
 729	KUNIT_EXPECT_LT(test,
 730			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
 731			0);
 732
 733	/* Should not have been any writes to registers */
 734	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 735}
 736
 737/*
 738 * Write to a volatile control when a different firmware is currently
 739 * loaded into the DSP.
 740 * Should return an error.
 741 */
 742static void cs_dsp_ctl_write_volatile_not_current_loaded_fw(struct kunit *test)
 743{
 744	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 745	struct cs_dsp_test *priv = test->priv;
 746	struct cs_dsp_test_local *local = priv->local;
 747	struct cs_dsp *dsp = priv->dsp;
 748	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 749	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
 750	int alg_idx = _find_alg_entry(test, param->alg_id);
 751	unsigned int reg, alg_base_words;
 752	struct cs_dsp_coeff_ctl *ctl;
 753	struct firmware *wmfw;
 754	u32 *reg_vals;
 755
 756	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 757	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 758
 759	/* Create some DSP data to be read into the control cache */
 760	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 761	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 762	reg += (alg_base_words + param->offs_words) *
 763		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 764	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 765
 766	/* Create control pointing to this data */
 767	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 768	def.mem_type = param->mem_type;
 769	def.offset_dsp_words = param->offs_words;
 770	def.length_bytes = param->len_bytes;
 771
 772	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 773					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 774					      "dummyalg", NULL);
 775	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 776	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 777
 778	/* Power-up DSP */
 779	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 780	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 781
 782	/* Power-down DSP then power-up with a different firmware */
 783	cs_dsp_power_down(dsp);
 784	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
 785	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
 786
 787	/* Drop expected writes and the regmap cache should be clean */
 788	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 789	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 790
 791	/* Write the control, it should return an error */
 792	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 793	KUNIT_ASSERT_NOT_NULL(test, ctl);
 794	KUNIT_EXPECT_LT(test,
 795			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
 796			0);
 797
 798	/* Should not have been any writes to registers */
 799	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 800}
 801
 802/*
 803 * Write to a volatile control when a different firmware is currently
 804 * running.
 805 * Should return an error.
 806 */
 807static void cs_dsp_ctl_write_volatile_not_current_running_fw(struct kunit *test)
 808{
 809	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 810	struct cs_dsp_test *priv = test->priv;
 811	struct cs_dsp_test_local *local = priv->local;
 812	struct cs_dsp *dsp = priv->dsp;
 813	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 814	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
 815	int alg_idx = _find_alg_entry(test, param->alg_id);
 816	unsigned int reg, alg_base_words;
 817	struct cs_dsp_coeff_ctl *ctl;
 818	struct firmware *wmfw;
 819	u32 *reg_vals;
 820
 821	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
 822	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 823
 824	/* Create some DSP data to be read into the control cache */
 825	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 826	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 827	reg += (alg_base_words + param->offs_words) *
 828		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 829	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
 830
 831	/* Create control pointing to this data */
 832	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
 833	def.mem_type = param->mem_type;
 834	def.offset_dsp_words = param->offs_words;
 835	def.length_bytes = param->len_bytes;
 836
 837	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 838					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 839					      "dummyalg", NULL);
 840	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 841	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 842
 843	/* Power-up DSP */
 844	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 845	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 846
 847	/* Power-down DSP then power-up with a different firmware */
 848	cs_dsp_power_down(dsp);
 849	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
 850	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
 851
 852	/* Start the firmware and add an action to stop it during cleanup */
 853	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 854	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
 855
 856	/* Drop expected writes and the regmap cache should be clean */
 857	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 858	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
 859
 860	/* Write the control, it should return an error */
 861	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 862	KUNIT_ASSERT_NOT_NULL(test, ctl);
 863	KUNIT_EXPECT_LT(test,
 864			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
 865			0);
 866
 867	/* Should not have been any writes to registers */
 868	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 869}
 870
 871/*
 872 * Read from an offset into the control data. Should return only the
 873 * portion of data from the offset position.
 874 */
 875static void cs_dsp_ctl_read_with_seek(struct kunit *test)
 876{
 877	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 878	struct cs_dsp_test *priv = test->priv;
 879	struct cs_dsp_test_local *local = priv->local;
 880	struct cs_dsp *dsp = priv->dsp;
 881	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 882	int alg_idx = _find_alg_entry(test, param->alg_id);
 883	unsigned int reg, alg_base_words;
 884	struct cs_dsp_coeff_ctl *ctl;
 885	struct firmware *wmfw;
 886	u32 *reg_vals, *readback;
 887	unsigned int seek_words;
 888
 889	def.flags = param->flags;
 890	def.mem_type = param->mem_type;
 891	def.offset_dsp_words = param->offs_words;
 892	def.length_bytes = 48;
 893
 894	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 895	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 896
 897	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 898	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 899
 900	/* Create some initial register content */
 901	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 902	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 903	reg += (alg_base_words + param->offs_words) *
 904		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 905	get_random_bytes(reg_vals, def.length_bytes);
 906	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
 907
 908	/* Create control pointing to this data */
 909	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 910					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 911					      "dummyalg", NULL);
 912	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 913	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 914
 915	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 916	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 917
 918	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 919	KUNIT_ASSERT_NOT_NULL(test, ctl);
 920
 921	/* Start the firmware and add an action to stop it during cleanup */
 922	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 923	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
 924
 925	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
 926		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
 927
 928		KUNIT_EXPECT_EQ(test,
 929				cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
 930								readback, len_bytes),
 931				0);
 932		KUNIT_EXPECT_MEMEQ(test, readback, &reg_vals[seek_words], len_bytes);
 933	}
 934}
 935
 936/*
 937 * Read from an offset into the control cache. Should return only the
 938 * portion of data from the offset position.
 939 * Same as cs_dsp_ctl_read_with_seek() except the control is cached
 940 * and the firmware is not running.
 941 */
 942static void cs_dsp_ctl_read_cache_with_seek(struct kunit *test)
 943{
 944	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
 945	struct cs_dsp_test *priv = test->priv;
 946	struct cs_dsp_test_local *local = priv->local;
 947	struct cs_dsp *dsp = priv->dsp;
 948	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 949	int alg_idx = _find_alg_entry(test, param->alg_id);
 950	unsigned int reg, alg_base_words;
 951	struct cs_dsp_coeff_ctl *ctl;
 952	struct firmware *wmfw;
 953	u32 *reg_vals, *readback;
 954	unsigned int seek_words;
 955
 956	def.flags = param->flags;
 957	def.mem_type = param->mem_type;
 958	def.offset_dsp_words = param->offs_words;
 959	def.length_bytes = 48;
 960
 961	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
 962	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
 963
 964	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
 965	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
 966
 967	/* Create some initial register content */
 968	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
 969	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
 970	reg += (alg_base_words + param->offs_words) *
 971		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 972	get_random_bytes(reg_vals, def.length_bytes);
 973	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
 974
 975	/* Create control pointing to this data */
 976	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 977					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
 978					      "dummyalg", NULL);
 979	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 980	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 981
 982	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 983	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 984
 985	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 986	KUNIT_ASSERT_NOT_NULL(test, ctl);
 987
 988	/* Start and stop the firmware so the read will come from the cache */
 989	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
 990	cs_dsp_stop(dsp);
 991
 992	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
 993		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
 994
 995		KUNIT_EXPECT_EQ(test,
 996				cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
 997								readback, len_bytes),
 998				0);
 999		KUNIT_EXPECT_MEMEQ(test, readback, &reg_vals[seek_words], len_bytes);
1000	}
1001}
1002
1003/*
1004 * Read less than the full length of data from a control. Should return
1005 * only the requested number of bytes.
1006 */
1007static void cs_dsp_ctl_read_truncated(struct kunit *test)
1008{
1009	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1010	struct cs_dsp_test *priv = test->priv;
1011	struct cs_dsp_test_local *local = priv->local;
1012	struct cs_dsp *dsp = priv->dsp;
1013	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1014	int alg_idx = _find_alg_entry(test, param->alg_id);
1015	unsigned int reg, alg_base_words;
1016	struct cs_dsp_coeff_ctl *ctl;
1017	struct firmware *wmfw;
1018	u32 *reg_vals, *readback;
1019	unsigned int len_bytes;
1020
1021	def.flags = param->flags;
1022	def.mem_type = param->mem_type;
1023	def.offset_dsp_words = param->offs_words;
1024	def.length_bytes = 48;
1025
1026	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1027	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1028
1029	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1030	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1031
1032	/* Create some initial register content */
1033	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1034	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1035	reg += (alg_base_words + param->offs_words) *
1036		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1037	get_random_bytes(reg_vals, def.length_bytes);
1038	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1039
1040	/* Create control pointing to this data */
1041	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1042					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1043					      "dummyalg", NULL);
1044	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1045	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1046
1047	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1048	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1049
1050	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1051	KUNIT_ASSERT_NOT_NULL(test, ctl);
1052
1053	/* Start the firmware and add an action to stop it during cleanup */
1054	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1055	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1056
1057	/* Reads are only allowed to be a multiple of the DSP word length */
1058	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1059		memset(readback, 0, def.length_bytes);
1060		KUNIT_EXPECT_EQ(test,
1061				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, len_bytes),
1062				0);
1063		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, len_bytes);
1064		KUNIT_EXPECT_MEMNEQ(test,
1065				    (u8 *)readback + len_bytes,
1066				    (u8 *)reg_vals + len_bytes,
1067				    def.length_bytes - len_bytes);
1068	}
1069}
1070
1071/*
1072 * Read less than the full length of data from a cached control.
1073 * Should return only the requested number of bytes.
1074 * Same as cs_dsp_ctl_read_truncated() except the control is cached
1075 * and the firmware is not running.
1076 */
1077static void cs_dsp_ctl_read_cache_truncated(struct kunit *test)
1078{
1079	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1080	struct cs_dsp_test *priv = test->priv;
1081	struct cs_dsp_test_local *local = priv->local;
1082	struct cs_dsp *dsp = priv->dsp;
1083	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1084	int alg_idx = _find_alg_entry(test, param->alg_id);
1085	unsigned int reg, alg_base_words;
1086	struct cs_dsp_coeff_ctl *ctl;
1087	struct firmware *wmfw;
1088	u32 *reg_vals, *readback;
1089	unsigned int len_bytes;
1090
1091	def.flags = param->flags;
1092	def.mem_type = param->mem_type;
1093	def.offset_dsp_words = param->offs_words;
1094	def.length_bytes = 48;
1095
1096	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1097	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1098
1099	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1100	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1101
1102	/* Create some initial register content */
1103	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1104	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1105	reg += (alg_base_words + param->offs_words) *
1106		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1107	get_random_bytes(reg_vals, def.length_bytes);
1108	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1109
1110	/* Create control pointing to this data */
1111	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1112					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1113					      "dummyalg", NULL);
1114	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1115	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1116
1117	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1118	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1119
1120	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1121	KUNIT_ASSERT_NOT_NULL(test, ctl);
1122
1123	/* Start and stop the firmware so the read will come from the cache */
1124	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1125	cs_dsp_stop(dsp);
1126
1127	/* Reads are only allowed to be a multiple of the DSP word length */
1128	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1129		memset(readback, 0, def.length_bytes);
1130		KUNIT_EXPECT_EQ(test,
1131				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, len_bytes),
1132				0);
1133		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, len_bytes);
1134		KUNIT_EXPECT_MEMNEQ(test,
1135				    (u8 *)readback + len_bytes,
1136				    (u8 *)reg_vals + len_bytes,
1137				    def.length_bytes - len_bytes);
1138	}
1139}
1140
1141/*
1142 * Write to an offset into the control data. Should only change the
1143 * portion of data from the offset position.
1144 */
1145static void cs_dsp_ctl_write_with_seek(struct kunit *test)
1146{
1147	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1148	struct cs_dsp_test *priv = test->priv;
1149	struct cs_dsp_test_local *local = priv->local;
1150	struct cs_dsp *dsp = priv->dsp;
1151	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1152	int alg_idx = _find_alg_entry(test, param->alg_id);
1153	unsigned int reg, alg_base_words;
1154	struct cs_dsp_coeff_ctl *ctl;
1155	struct firmware *wmfw;
1156	u32 *reg_vals, *readback, *new_data;
1157	unsigned int seek_words;
1158
1159	def.flags = param->flags;
1160	def.mem_type = param->mem_type;
1161	def.offset_dsp_words = param->offs_words;
1162	def.length_bytes = 48;
1163
1164	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1165	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1166
1167	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1168	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1169
1170	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1171	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1172
1173	/* Create some initial register content */
1174	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1175	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1176	reg += (alg_base_words + param->offs_words) *
1177		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1178	get_random_bytes(reg_vals, def.length_bytes);
1179	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1180
1181	/* Create control pointing to this data */
1182	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1183					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1184					      "dummyalg", NULL);
1185	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1186	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1187
1188	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1189	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1190
1191	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1192	KUNIT_ASSERT_NOT_NULL(test, ctl);
1193
1194	/* Start the firmware and add an action to stop it during cleanup */
1195	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1196	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1197
1198	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
1199		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
1200
1201		/* Reset the register values to the test data */
1202		regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1203
1204		get_random_bytes(new_data, def.length_bytes);
1205		KUNIT_EXPECT_EQ(test,
1206				cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1207								 new_data, len_bytes),
1208				1);
1209		KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, def.length_bytes),
1210				0);
1211		/* Initial portion of readback should be unchanged */
1212		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, seek_words * sizeof(u32));
1213		KUNIT_EXPECT_MEMEQ(test, &readback[seek_words], new_data, len_bytes);
1214	}
1215}
1216
1217/*
1218 * Write to an offset into the control cache. Should only change the
1219 * portion of data from the offset position.
1220 * Same as cs_dsp_ctl_write_with_seek() except the control is cached
1221 * and the firmware is not running.
1222 */
1223static void cs_dsp_ctl_write_cache_with_seek(struct kunit *test)
1224{
1225	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1226	struct cs_dsp_test *priv = test->priv;
1227	struct cs_dsp_test_local *local = priv->local;
1228	struct cs_dsp *dsp = priv->dsp;
1229	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1230	int alg_idx = _find_alg_entry(test, param->alg_id);
1231	unsigned int reg, alg_base_words;
1232	struct cs_dsp_coeff_ctl *ctl;
1233	struct firmware *wmfw;
1234	u32 *reg_vals, *readback, *new_data;
1235	unsigned int seek_words;
1236
1237	def.flags = param->flags;
1238	def.mem_type = param->mem_type;
1239	def.offset_dsp_words = param->offs_words;
1240	def.length_bytes = 48;
1241
1242	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1243	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1244
1245	readback = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1246	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1247
1248	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1249	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1250
1251	/* Create some initial register content */
1252	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1253	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1254	reg += (alg_base_words + param->offs_words) *
1255		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1256	get_random_bytes(reg_vals, def.length_bytes);
1257	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1258
1259	/* Create control pointing to this data */
1260	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1261					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1262					      "dummyalg", NULL);
1263	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1264	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1265
1266	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1267	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1268
1269	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1270	KUNIT_ASSERT_NOT_NULL(test, ctl);
1271
1272	/* Start and stop the firmware so the read will come from the cache */
1273	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1274	cs_dsp_stop(dsp);
1275
1276	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
1277		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
1278
1279		/* Reset the cache to the test data */
1280		KUNIT_EXPECT_GE(test,
1281				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1282								 def.length_bytes),
1283				0);
1284
1285		get_random_bytes(new_data, def.length_bytes);
1286		KUNIT_EXPECT_EQ(test,
1287				cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1288								 new_data, len_bytes),
1289				1);
1290
1291		memset(readback, 0, def.length_bytes);
1292		KUNIT_EXPECT_EQ(test,
1293				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback,
1294								def.length_bytes),
1295				0);
1296		/* Initial portion of readback should be unchanged */
1297		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, seek_words * sizeof(u32));
1298		KUNIT_EXPECT_MEMEQ(test, &readback[seek_words], new_data, len_bytes);
1299	}
1300}
1301
1302/*
1303 * Write less than the full length of data to a control. Should only
1304 * change the requested number of bytes.
1305 */
1306static void cs_dsp_ctl_write_truncated(struct kunit *test)
1307{
1308	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1309	struct cs_dsp_test *priv = test->priv;
1310	struct cs_dsp_test_local *local = priv->local;
1311	struct cs_dsp *dsp = priv->dsp;
1312	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1313	int alg_idx = _find_alg_entry(test, param->alg_id);
1314	unsigned int reg, alg_base_words;
1315	struct cs_dsp_coeff_ctl *ctl;
1316	struct firmware *wmfw;
1317	u32 *reg_vals, *readback, *new_data;
1318	unsigned int len_bytes;
1319
1320	def.flags = param->flags;
1321	def.mem_type = param->mem_type;
1322	def.offset_dsp_words = param->offs_words;
1323	def.length_bytes = 48;
1324
1325	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1326	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1327
1328	readback = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1329	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1330
1331	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1332	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1333
1334	/* Create some initial register content */
1335	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1336	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1337	reg += (alg_base_words + param->offs_words) *
1338		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1339	get_random_bytes(reg_vals, def.length_bytes);
1340	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1341
1342	/* Create control pointing to this data */
1343	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1344					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1345					      "dummyalg", NULL);
1346	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1347	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1348
1349	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1350	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1351
1352	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1353	KUNIT_ASSERT_NOT_NULL(test, ctl);
1354
1355	/* Start the firmware and add an action to stop it during cleanup */
1356	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1357	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1358
1359	/* Writes are only allowed to be a multiple of the DSP word length */
1360	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1361		/* Reset the register values to the test data */
1362		regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1363
1364		get_random_bytes(new_data, def.length_bytes);
1365		KUNIT_EXPECT_EQ(test,
1366				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, new_data, len_bytes),
1367				1);
1368
1369		memset(readback, 0, def.length_bytes);
1370		KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, def.length_bytes),
1371				0);
1372		KUNIT_EXPECT_MEMEQ(test, readback, new_data, len_bytes);
1373		KUNIT_EXPECT_MEMEQ(test,
1374				   (u8 *)readback + len_bytes,
1375				   (u8 *)reg_vals + len_bytes,
1376				   def.length_bytes - len_bytes);
1377	}
1378}
1379
1380/*
1381 * Write less than the full length of data to a cached control.
1382 * Should only change the requested number of bytes.
1383 * Same as cs_dsp_ctl_write_truncated() except the control is cached
1384 * and the firmware is not running.
1385 */
1386static void cs_dsp_ctl_write_cache_truncated(struct kunit *test)
1387{
1388	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1389	struct cs_dsp_test *priv = test->priv;
1390	struct cs_dsp_test_local *local = priv->local;
1391	struct cs_dsp *dsp = priv->dsp;
1392	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1393	int alg_idx = _find_alg_entry(test, param->alg_id);
1394	unsigned int reg, alg_base_words;
1395	struct cs_dsp_coeff_ctl *ctl;
1396	struct firmware *wmfw;
1397	u32 *reg_vals, *readback, *new_data;
1398	unsigned int len_bytes;
1399
1400	def.flags = param->flags;
1401	def.mem_type = param->mem_type;
1402	def.offset_dsp_words = param->offs_words;
1403	def.length_bytes = 48;
1404
1405	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1406	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1407
1408	readback = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1409	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1410
1411	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1412	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1413
1414	/* Create some initial register content */
1415	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1416	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1417	reg += (alg_base_words + param->offs_words) *
1418		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1419	get_random_bytes(reg_vals, def.length_bytes);
1420	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1421
1422	/* Create control pointing to this data */
1423	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1424					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1425					      "dummyalg", NULL);
1426	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1427	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1428
1429	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1430	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1431
1432	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1433	KUNIT_ASSERT_NOT_NULL(test, ctl);
1434
1435	/* Start and stop the firmware so the read will come from the cache */
1436	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1437	cs_dsp_stop(dsp);
1438
1439	/* Writes are only allowed to be a multiple of the DSP word length */
1440	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1441		/* Reset the cache to the test data */
1442		KUNIT_EXPECT_GE(test,
1443				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1444								 def.length_bytes),
1445				0);
1446
1447		get_random_bytes(new_data, def.length_bytes);
1448		KUNIT_EXPECT_EQ(test,
1449				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, new_data, len_bytes),
1450				1);
1451
1452		memset(readback, 0, def.length_bytes);
1453		KUNIT_EXPECT_EQ(test,
1454				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback,
1455								def.length_bytes),
1456				0);
1457		KUNIT_EXPECT_MEMEQ(test, readback, new_data, len_bytes);
1458		KUNIT_EXPECT_MEMEQ(test,
1459				   (u8 *)readback + len_bytes,
1460				   (u8 *)reg_vals + len_bytes,
1461				   def.length_bytes - len_bytes);
1462	}
1463}
1464
1465/*
1466 * Read from an offset that is beyond the end of the control data.
1467 * Should return an error.
1468 */
1469static void cs_dsp_ctl_read_with_seek_oob(struct kunit *test)
1470{
1471	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1472	struct cs_dsp_test *priv = test->priv;
1473	struct cs_dsp_test_local *local = priv->local;
1474	struct cs_dsp *dsp = priv->dsp;
1475	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1476	int alg_idx = _find_alg_entry(test, param->alg_id);
1477	unsigned int reg, alg_base_words;
1478	struct cs_dsp_coeff_ctl *ctl;
1479	struct firmware *wmfw;
1480	u32 *reg_vals;
1481	unsigned int seek_words;
1482
1483	def.flags = param->flags;
1484	def.mem_type = param->mem_type;
1485	def.offset_dsp_words = param->offs_words;
1486	def.length_bytes = param->len_bytes;
1487
1488	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1489	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1490
1491	/* Create some initial register content */
1492	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1493	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1494	reg += (alg_base_words + param->offs_words) *
1495		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1496	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1497
1498	/* Create control pointing to this data */
1499	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1500					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1501					      "dummyalg", NULL);
1502	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1503	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1504
1505	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1506	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1507
1508	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1509	KUNIT_ASSERT_NOT_NULL(test, ctl);
1510
1511	/* Start the firmware and add an action to stop it during cleanup */
1512	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1513	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1514
1515	seek_words = def.length_bytes / sizeof(u32);
1516	KUNIT_EXPECT_LT(test,
1517			cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
1518							reg_vals, def.length_bytes),
1519			0);
1520
1521	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1522		/* Stop firmware and repeat the read from the cache */
1523		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1524		KUNIT_ASSERT_FALSE(test, dsp->running);
1525
1526		KUNIT_EXPECT_LT(test,
1527				cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
1528								reg_vals, def.length_bytes),
1529				0);
1530	}
1531}
1532
1533/*
1534 * Read more data than the length of the control data.
1535 * Should return an error.
1536 */
1537static void cs_dsp_ctl_read_with_length_overflow(struct kunit *test)
1538{
1539	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1540	struct cs_dsp_test *priv = test->priv;
1541	struct cs_dsp_test_local *local = priv->local;
1542	struct cs_dsp *dsp = priv->dsp;
1543	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1544	int alg_idx = _find_alg_entry(test, param->alg_id);
1545	unsigned int reg, alg_base_words;
1546	struct cs_dsp_coeff_ctl *ctl;
1547	struct firmware *wmfw;
1548	u32 *reg_vals;
1549
1550	def.flags = param->flags;
1551	def.mem_type = param->mem_type;
1552	def.offset_dsp_words = param->offs_words;
1553	def.length_bytes = param->len_bytes;
1554
1555	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1556	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1557
1558	/* Create some initial register content */
1559	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1560	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1561	reg += (alg_base_words + param->offs_words) *
1562		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1563	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1564
1565	/* Create control pointing to this data */
1566	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1567					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1568					      "dummyalg", NULL);
1569	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1570	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1571
1572	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1573	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1574
1575	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1576	KUNIT_ASSERT_NOT_NULL(test, ctl);
1577
1578	/* Start the firmware and add an action to stop it during cleanup */
1579	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1580	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1581
1582	KUNIT_EXPECT_LT(test,
1583			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, def.length_bytes + 1),
1584			0);
1585
1586	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1587		/* Stop firmware and repeat the read from the cache */
1588		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1589		KUNIT_ASSERT_FALSE(test, dsp->running);
1590
1591		KUNIT_EXPECT_LT(test,
1592				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals,
1593								def.length_bytes + 1),
1594				0);
1595	}
1596}
1597
1598/*
1599 * Read with a seek and length that ends beyond the end of control data.
1600 * Should return an error.
1601 */
1602static void cs_dsp_ctl_read_with_seek_and_length_oob(struct kunit *test)
1603{
1604	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1605	struct cs_dsp_test *priv = test->priv;
1606	struct cs_dsp_test_local *local = priv->local;
1607	struct cs_dsp *dsp = priv->dsp;
1608	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1609	int alg_idx = _find_alg_entry(test, param->alg_id);
1610	unsigned int reg, alg_base_words;
1611	struct cs_dsp_coeff_ctl *ctl;
1612	struct firmware *wmfw;
1613	u32 *reg_vals;
1614
1615	def.flags = param->flags;
1616	def.mem_type = param->mem_type;
1617	def.offset_dsp_words = param->offs_words;
1618	def.length_bytes = param->len_bytes;
1619
1620	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1621	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1622
1623	/* Create some initial register content */
1624	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1625	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1626	reg += (alg_base_words + param->offs_words) *
1627		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1628	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1629
1630	/* Create control pointing to this data */
1631	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1632					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1633					      "dummyalg", NULL);
1634	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1635	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1636
1637	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1638	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1639
1640	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1641	KUNIT_ASSERT_NOT_NULL(test, ctl);
1642
1643	/* Start the firmware and add an action to stop it during cleanup */
1644	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1645	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1646
1647	/*
1648	 * Read full control length but at a start offset of 1 so that
1649	 * offset + length exceeds the length of the control.
1650	 */
1651	KUNIT_EXPECT_LT(test,
1652			cs_dsp_coeff_lock_and_read_ctrl(ctl, 1, reg_vals, def.length_bytes),
1653			0);
1654
1655	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1656		/* Stop firmware and repeat the read from the cache */
1657		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1658		KUNIT_ASSERT_FALSE(test, dsp->running);
1659
1660		KUNIT_EXPECT_LT(test,
1661				cs_dsp_coeff_lock_and_read_ctrl(ctl, 1, reg_vals,
1662								def.length_bytes),
1663				0);
1664	}
1665}
1666
1667/*
1668 * Write to an offset that is beyond the end of the control data.
1669 * Should return an error without touching any registers.
1670 */
1671static void cs_dsp_ctl_write_with_seek_oob(struct kunit *test)
1672{
1673	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1674	struct cs_dsp_test *priv = test->priv;
1675	struct cs_dsp_test_local *local = priv->local;
1676	struct cs_dsp *dsp = priv->dsp;
1677	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1678	int alg_idx = _find_alg_entry(test, param->alg_id);
1679	unsigned int reg, alg_base_words;
1680	struct cs_dsp_coeff_ctl *ctl;
1681	struct firmware *wmfw;
1682	u32 *reg_vals;
1683	unsigned int seek_words;
1684
1685	def.flags = param->flags;
1686	def.mem_type = param->mem_type;
1687	def.offset_dsp_words = param->offs_words;
1688	def.length_bytes = param->len_bytes;
1689
1690	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1691	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1692
1693	/* Create some initial register content */
1694	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1695	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1696	reg += (alg_base_words + param->offs_words) *
1697		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1698	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1699
1700	/* Create control pointing to this data */
1701	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1702					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1703					      "dummyalg", NULL);
1704	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1705	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1706
1707	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1708	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1709
1710	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1711	KUNIT_ASSERT_NOT_NULL(test, ctl);
1712
1713	/* Start the firmware and add an action to stop it during cleanup */
1714	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1715	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1716
1717	/* Drop expected writes and the regmap cache should be clean */
1718	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1719	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1720
1721	get_random_bytes(reg_vals, def.length_bytes);
1722	seek_words = def.length_bytes / sizeof(u32);
1723	KUNIT_EXPECT_LT(test,
1724			cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1725							 reg_vals, def.length_bytes),
1726			0);
1727
1728	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1729		/* Stop firmware and repeat the write to the cache */
1730		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1731		KUNIT_ASSERT_FALSE(test, dsp->running);
1732
1733		get_random_bytes(reg_vals, def.length_bytes);
1734		KUNIT_EXPECT_LT(test,
1735				cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1736								 reg_vals, def.length_bytes),
1737				0);
1738	}
1739
1740	/* Check that it didn't write any registers */
1741	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1742}
1743
1744/*
1745 * Write more data than the length of the control data.
1746 * Should return an error.
1747 */
1748static void cs_dsp_ctl_write_with_length_overflow(struct kunit *test)
1749{
1750	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1751	struct cs_dsp_test *priv = test->priv;
1752	struct cs_dsp_test_local *local = priv->local;
1753	struct cs_dsp *dsp = priv->dsp;
1754	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1755	int alg_idx = _find_alg_entry(test, param->alg_id);
1756	unsigned int reg, alg_base_words;
1757	struct cs_dsp_coeff_ctl *ctl;
1758	struct firmware *wmfw;
1759	u32 *reg_vals;
1760
1761	def.flags = param->flags;
1762	def.mem_type = param->mem_type;
1763	def.offset_dsp_words = param->offs_words;
1764	def.length_bytes = param->len_bytes;
1765
1766	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1767	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1768
1769	/* Create some initial register content */
1770	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1771	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1772	reg += (alg_base_words + param->offs_words) *
1773		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1774	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1775
1776	/* Create control pointing to this data */
1777	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1778					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1779					      "dummyalg", NULL);
1780	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1781	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1782
1783	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1784	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1785
1786	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1787	KUNIT_ASSERT_NOT_NULL(test, ctl);
1788
1789	/* Start the firmware and add an action to stop it during cleanup */
1790	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1791	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1792
1793	/* Drop expected writes and the regmap cache should be clean */
1794	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1795	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1796
1797	get_random_bytes(reg_vals, def.length_bytes);
1798	KUNIT_EXPECT_LT(test,
1799			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, def.length_bytes + 1),
1800			0);
1801
1802	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1803		/* Stop firmware and repeat the write to the cache */
1804		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1805		KUNIT_ASSERT_FALSE(test, dsp->running);
1806
1807		get_random_bytes(reg_vals, def.length_bytes);
1808		KUNIT_EXPECT_LT(test,
1809				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1810								 def.length_bytes + 1),
1811				0);
1812	}
1813
1814	/* Check that it didn't write any registers */
1815	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1816}
1817
1818/*
1819 * Write with a seek and length that ends beyond the end of control data.
1820 * Should return an error.
1821 */
1822static void cs_dsp_ctl_write_with_seek_and_length_oob(struct kunit *test)
1823{
1824	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1825	struct cs_dsp_test *priv = test->priv;
1826	struct cs_dsp_test_local *local = priv->local;
1827	struct cs_dsp *dsp = priv->dsp;
1828	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1829	int alg_idx = _find_alg_entry(test, param->alg_id);
1830	unsigned int reg, alg_base_words;
1831	struct cs_dsp_coeff_ctl *ctl;
1832	struct firmware *wmfw;
1833	u32 *reg_vals;
1834
1835	def.flags = param->flags;
1836	def.mem_type = param->mem_type;
1837	def.offset_dsp_words = param->offs_words;
1838	def.length_bytes = param->len_bytes;
1839
1840	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1841	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1842
1843	/* Create some initial register content */
1844	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1845	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1846	reg += (alg_base_words + param->offs_words) *
1847		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1848	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1849
1850	/* Create control pointing to this data */
1851	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1852					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1853					      "dummyalg", NULL);
1854	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1855	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1856
1857	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1858	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1859
1860	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1861	KUNIT_ASSERT_NOT_NULL(test, ctl);
1862
1863	/* Start the firmware and add an action to stop it during cleanup */
1864	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1865	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1866
1867	/* Drop expected writes and the regmap cache should be clean */
1868	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1869	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1870
1871	/*
1872	 * Write full control length but at a start offset of 1 so that
1873	 * offset + length exceeeds the length of the control.
1874	 */
1875	get_random_bytes(reg_vals, def.length_bytes);
1876	KUNIT_EXPECT_LT(test,
1877			cs_dsp_coeff_lock_and_write_ctrl(ctl, 1, reg_vals, def.length_bytes),
1878			0);
1879
1880	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1881		/* Stop firmware and repeat the write to the cache */
1882		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1883		KUNIT_ASSERT_FALSE(test, dsp->running);
1884
1885		get_random_bytes(reg_vals, def.length_bytes);
1886		KUNIT_EXPECT_LT(test,
1887				cs_dsp_coeff_lock_and_write_ctrl(ctl, 1, reg_vals,
1888								 def.length_bytes),
1889				0);
1890	}
1891
1892	/* Check that it didn't write any registers */
1893	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1894}
1895
1896/*
1897 * Read from a write-only control. This is legal because controls can
1898 * always be read. Write-only only indicates that it is not useful to
1899 * populate the cache from the DSP memory.
1900 */
1901static void cs_dsp_ctl_read_from_writeonly(struct kunit *test)
1902{
1903	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1904	struct cs_dsp_test *priv = test->priv;
1905	struct cs_dsp_test_local *local = priv->local;
1906	struct cs_dsp *dsp = priv->dsp;
1907	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1908	int alg_idx = _find_alg_entry(test, param->alg_id);
1909	struct cs_dsp_coeff_ctl *ctl;
1910	struct firmware *wmfw;
1911	u32 *ctl_vals, *readback;
1912
1913	/* Sanity check parameters */
1914	KUNIT_ASSERT_TRUE(test, param->flags & WMFW_CTL_FLAG_WRITEABLE);
1915	KUNIT_ASSERT_FALSE(test, param->flags & WMFW_CTL_FLAG_READABLE);
1916
1917	def.flags = param->flags;
1918	def.mem_type = param->mem_type;
1919	def.offset_dsp_words = param->offs_words;
1920	def.length_bytes = param->len_bytes;
1921
1922	ctl_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1923	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
1924
1925	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1926	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1927
1928	/* Create control pointing to this data */
1929	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1930					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1931					      "dummyalg", NULL);
1932	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1933	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1934
1935	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1936	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1937
1938	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1939	KUNIT_ASSERT_NOT_NULL(test, ctl);
1940
1941	/* Start the firmware and add an action to stop it during cleanup */
1942	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1943	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1944
1945	/* Write some test data to the control */
1946	get_random_bytes(ctl_vals, def.length_bytes);
1947	KUNIT_EXPECT_EQ(test,
1948			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, def.length_bytes),
1949			1);
1950
1951	/* Read back the data */
1952	KUNIT_EXPECT_EQ(test,
1953			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, def.length_bytes),
1954			0);
1955	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, def.length_bytes);
1956
1957	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1958		/* Stop firmware and repeat the read from the cache */
1959		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1960		KUNIT_ASSERT_FALSE(test, dsp->running);
1961
1962		memset(readback, 0, def.length_bytes);
1963		KUNIT_EXPECT_EQ(test,
1964				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback,
1965								def.length_bytes),
1966				0);
1967		KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, def.length_bytes);
1968	}
1969}
1970
1971/*
1972 * Write to a read-only control.
1973 * This should return an error without writing registers.
1974 */
1975static void cs_dsp_ctl_write_to_readonly(struct kunit *test)
1976{
1977	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1978	struct cs_dsp_test *priv = test->priv;
1979	struct cs_dsp_test_local *local = priv->local;
1980	struct cs_dsp *dsp = priv->dsp;
1981	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1982	int alg_idx = _find_alg_entry(test, param->alg_id);
1983	unsigned int reg, alg_base_words;
1984	struct cs_dsp_coeff_ctl *ctl;
1985	struct firmware *wmfw;
1986	u32 *reg_vals;
1987
1988	/* Sanity check parameters */
1989	KUNIT_ASSERT_FALSE(test, param->flags & WMFW_CTL_FLAG_WRITEABLE);
1990	KUNIT_ASSERT_TRUE(test, param->flags & WMFW_CTL_FLAG_READABLE);
1991
1992	def.flags = param->flags;
1993	def.mem_type = param->mem_type;
1994	def.offset_dsp_words = param->offs_words;
1995	def.length_bytes = param->len_bytes;
1996
1997	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1998	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1999
2000	/* Create some initial register content */
2001	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2002	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2003	reg += (alg_base_words + param->offs_words) *
2004		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2005	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
2006
2007	/* Create control pointing to this data */
2008	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2009					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
2010					      "dummyalg", NULL);
2011	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2012	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2013
2014	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2015	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2016
2017	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2018	KUNIT_ASSERT_NOT_NULL(test, ctl);
2019
2020	/* Start the firmware and add an action to stop it during cleanup */
2021	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2022	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2023
2024	/* Drop expected writes and the regmap cache should be clean */
2025	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2026	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
2027
2028	get_random_bytes(reg_vals, def.length_bytes);
2029	KUNIT_EXPECT_LT(test,
2030			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, def.length_bytes),
2031			0);
2032
2033	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
2034		/* Stop firmware and repeat the write to the cache */
2035		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2036		KUNIT_ASSERT_FALSE(test, dsp->running);
2037
2038		get_random_bytes(reg_vals, def.length_bytes);
2039		KUNIT_EXPECT_LT(test,
2040				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
2041								 def.length_bytes),
2042				0);
2043	}
2044
2045	/* Check that it didn't write any registers */
2046	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2047}
2048
2049static int cs_dsp_ctl_rw_test_common_init(struct kunit *test, struct cs_dsp *dsp,
2050					  int wmfw_version)
2051{
2052	struct cs_dsp_test *priv;
2053	struct cs_dsp_test_local *local;
2054	struct device *test_dev;
2055	int ret;
2056
2057	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2058	if (!priv)
2059		return -ENOMEM;
2060
2061	local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2062	if (!local)
2063		return -ENOMEM;
2064
2065	priv->test = test;
2066	priv->dsp = dsp;
2067	test->priv = priv;
2068	priv->local = local;
2069	priv->local->wmfw_version = wmfw_version;
2070
2071	/* Create dummy struct device */
2072	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2073	if (IS_ERR(test_dev))
2074		return PTR_ERR(test_dev);
2075
2076	dsp->dev = get_device(test_dev);
2077	if (!dsp->dev)
2078		return -ENODEV;
2079
2080	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2081	if (ret)
2082		return ret;
2083
2084	dev_set_drvdata(dsp->dev, priv);
2085
2086	/* Allocate regmap */
2087	ret = cs_dsp_mock_regmap_init(priv);
2088	if (ret)
2089		return ret;
2090
2091	/*
2092	 * There must always be a XM header with at least 1 algorithm, so create
2093	 * a dummy one that tests can use and extract it to a data blob.
2094	 */
2095	local->xm_header = cs_dsp_create_mock_xm_header(priv,
2096							cs_dsp_ctl_rw_test_algs,
2097							ARRAY_SIZE(cs_dsp_ctl_rw_test_algs));
2098	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
2099
2100	/* Create wmfw builder */
2101	local->wmfw_builder = _create_dummy_wmfw(test);
2102
2103	/* Init cs_dsp */
2104	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2105	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2106
2107	switch (dsp->type) {
2108	case WMFW_ADSP2:
2109		ret = cs_dsp_adsp2_init(dsp);
2110		break;
2111	case WMFW_HALO:
2112		ret = cs_dsp_halo_init(dsp);
2113		break;
2114	default:
2115		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2116		return -EINVAL;
2117	}
2118
2119	if (ret)
2120		return ret;
2121
2122	/* Automatically call cs_dsp_remove() when test case ends */
2123	return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2124}
2125
2126static int cs_dsp_ctl_rw_test_halo_init(struct kunit *test)
2127{
2128	struct cs_dsp *dsp;
2129
2130	/* Fill in cs_dsp and initialize */
2131	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2132	if (!dsp)
2133		return -ENOMEM;
2134
2135	dsp->num = 1;
2136	dsp->type = WMFW_HALO;
2137	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2138	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2139	dsp->base = cs_dsp_mock_halo_core_base;
2140	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2141
2142	return cs_dsp_ctl_rw_test_common_init(test, dsp, 3);
2143}
2144
2145static int cs_dsp_ctl_rw_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
2146{
2147	struct cs_dsp *dsp;
2148
2149	/* Fill in cs_dsp and initialize */
2150	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2151	if (!dsp)
2152		return -ENOMEM;
2153
2154	dsp->num = 1;
2155	dsp->type = WMFW_ADSP2;
2156	dsp->rev = 1;
2157	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2158	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2159	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2160
2161	return cs_dsp_ctl_rw_test_common_init(test, dsp, wmfw_ver);
2162}
2163
2164static int cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1_init(struct kunit *test)
2165{
2166	return cs_dsp_ctl_rw_test_adsp2_32bit_init(test, 1);
2167}
2168
2169static int cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2_init(struct kunit *test)
2170{
2171	return cs_dsp_ctl_rw_test_adsp2_32bit_init(test, 2);
2172}
2173
2174static int cs_dsp_ctl_rw_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
2175{
2176	struct cs_dsp *dsp;
2177
2178	/* Fill in cs_dsp and initialize */
2179	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2180	if (!dsp)
2181		return -ENOMEM;
2182
2183	dsp->num = 1;
2184	dsp->type = WMFW_ADSP2;
2185	dsp->rev = 0;
2186	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2187	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2188	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2189
2190	return cs_dsp_ctl_rw_test_common_init(test, dsp, wmfw_ver);
2191}
2192
2193static int cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1_init(struct kunit *test)
2194{
2195	return cs_dsp_ctl_rw_test_adsp2_16bit_init(test, 1);
2196}
2197
2198static int cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2_init(struct kunit *test)
2199{
2200	return cs_dsp_ctl_rw_test_adsp2_16bit_init(test, 2);
2201}
2202
2203static void cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_rw_test_param *param,
2204				      char *desc)
2205{
2206	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg:%#x %s@%u len:%u flags:%#x",
2207		 param->alg_id, cs_dsp_mem_region_name(param->mem_type),
2208		 param->offs_words, param->len_bytes, param->flags);
2209}
2210
2211/* All parameters populated, with various lengths */
2212static const struct cs_dsp_ctl_rw_test_param all_pop_varying_len_cases[] = {
2213	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2214	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 8 },
2215	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 12 },
2216	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 16 },
2217	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 48 },
2218	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 100 },
2219	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512 },
2220	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 1000 },
2221};
2222KUNIT_ARRAY_PARAM(all_pop_varying_len, all_pop_varying_len_cases,
2223		  cs_dsp_ctl_all_param_desc);
2224
2225/* All parameters populated, with various offsets */
2226static const struct cs_dsp_ctl_rw_test_param all_pop_varying_offset_cases[] = {
2227	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 0,   .len_bytes = 4 },
2228	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1,   .len_bytes = 4 },
2229	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 2,   .len_bytes = 4 },
2230	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 3,   .len_bytes = 4 },
2231	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 8,   .len_bytes = 4 },
2232	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 10,  .len_bytes = 4 },
2233	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 128, .len_bytes = 4 },
2234	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 180, .len_bytes = 4 },
2235};
2236KUNIT_ARRAY_PARAM(all_pop_varying_offset, all_pop_varying_offset_cases,
2237		  cs_dsp_ctl_all_param_desc);
2238
2239/* All parameters populated, with various X and Y memory regions */
2240static const struct cs_dsp_ctl_rw_test_param all_pop_varying_xy_cases[] = {
2241	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_XM, .offs_words = 1, .len_bytes = 4 },
2242	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2243};
2244KUNIT_ARRAY_PARAM(all_pop_varying_xy, all_pop_varying_xy_cases,
2245		  cs_dsp_ctl_all_param_desc);
2246
2247/* All parameters populated, using ZM */
2248static const struct cs_dsp_ctl_rw_test_param all_pop_z_cases[] = {
2249	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_ZM, .offs_words = 1, .len_bytes = 4 },
2250};
2251KUNIT_ARRAY_PARAM(all_pop_z, all_pop_z_cases, cs_dsp_ctl_all_param_desc);
2252
2253/* All parameters populated, with various algorithm ids */
2254static const struct cs_dsp_ctl_rw_test_param all_pop_varying_alg_cases[] = {
2255	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2256	{ .alg_id = 0xb,      .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2257	{ .alg_id = 0x9f1234, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2258	{ .alg_id = 0xff00ff, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2259};
2260KUNIT_ARRAY_PARAM(all_pop_varying_alg, all_pop_varying_alg_cases,
2261		  cs_dsp_ctl_all_param_desc);
2262
2263/*
2264 * All parameters populated, with all combinations of flags for a
2265 * readable control.
2266 */
2267static const struct cs_dsp_ctl_rw_test_param all_pop_readable_flags_cases[] = {
2268	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2269	  .flags = 0
2270	},
2271	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2272	  .flags = WMFW_CTL_FLAG_READABLE,
2273	},
2274	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2275	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2276	},
2277	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2278	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2279	},
2280	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2281	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2282	},
2283	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2284	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE,
2285	},
2286	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2287	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2288	},
2289	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2290	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2291	},
2292	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2293	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2294		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2295	},
2296};
2297KUNIT_ARRAY_PARAM(all_pop_readable_flags,
2298		  all_pop_readable_flags_cases,
2299		  cs_dsp_ctl_all_param_desc);
2300
2301/*
2302 * All parameters populated, with all combinations of flags for a
2303 * read-only control
2304 */
2305static const struct cs_dsp_ctl_rw_test_param all_pop_readonly_flags_cases[] = {
2306	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2307	  .flags = WMFW_CTL_FLAG_READABLE,
2308	},
2309	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2310	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2311	},
2312	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2313	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE,
2314	},
2315	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2316	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2317	},
2318};
2319KUNIT_ARRAY_PARAM(all_pop_readonly_flags,
2320		  all_pop_readonly_flags_cases,
2321		  cs_dsp_ctl_all_param_desc);
2322
2323/*
2324 * All parameters populated, with all combinations of flags for a
2325 * non-volatile readable control
2326 */
2327static const struct cs_dsp_ctl_rw_test_param all_pop_nonvol_readable_flags_cases[] = {
2328	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2329	  .flags = 0
2330	},
2331	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2332	  .flags = WMFW_CTL_FLAG_READABLE,
2333	},
2334	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2335	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2336	},
2337	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2338	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2339	},
2340	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2341	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2342	},
2343};
2344KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_flags,
2345		  all_pop_nonvol_readable_flags_cases,
2346		  cs_dsp_ctl_all_param_desc);
2347
2348/*
2349 * All parameters populated, with all combinations of flags for a
2350 * writeable control
2351 */
2352static const struct cs_dsp_ctl_rw_test_param all_pop_writeable_flags_cases[] = {
2353	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2354	  .flags = 0
2355	},
2356	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2357	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2358	},
2359	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2360	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2361	},
2362	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2363	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2364	},
2365	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2366	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2367	},
2368	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2369	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE,
2370	},
2371	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2372	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2373	},
2374	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2375	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2376	},
2377	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2378	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2379		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2380	},
2381};
2382KUNIT_ARRAY_PARAM(all_pop_writeable_flags,
2383		  all_pop_writeable_flags_cases,
2384		  cs_dsp_ctl_all_param_desc);
2385
2386/*
2387 * All parameters populated, with all combinations of flags for a
2388 * write-only control
2389 */
2390static const struct cs_dsp_ctl_rw_test_param all_pop_writeonly_flags_cases[] = {
2391	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2392	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2393	},
2394	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2395	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2396	},
2397	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2398	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE,
2399	},
2400	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2401	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2402	},
2403};
2404KUNIT_ARRAY_PARAM(all_pop_writeonly_flags,
2405		  all_pop_writeonly_flags_cases,
2406		  cs_dsp_ctl_all_param_desc);
2407
2408/*
2409 * All parameters populated, with all combinations of flags for a
2410 * non-volatile writeable control
2411 */
2412static const struct cs_dsp_ctl_rw_test_param all_pop_nonvol_writeable_flags_cases[] = {
2413	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2414	  .flags = 0
2415	},
2416	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2417	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2418	},
2419	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2420	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2421	},
2422	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2423	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2424	},
2425	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2426	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2427	},
2428};
2429KUNIT_ARRAY_PARAM(all_pop_nonvol_writeable_flags,
2430		  all_pop_nonvol_writeable_flags_cases,
2431		  cs_dsp_ctl_all_param_desc);
2432
2433/*
2434 * All parameters populated, with all combinations of flags for a
2435 * volatile readable control.
2436 */
2437static const struct cs_dsp_ctl_rw_test_param all_pop_volatile_readable_flags_cases[] = {
2438	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2439	  .flags = 0 /* flags == 0 is volatile while firmware is running */
2440	},
2441	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2442	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE,
2443	},
2444	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2445	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2446	},
2447	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2448	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2449	},
2450	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2451	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2452		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2453	},
2454};
2455KUNIT_ARRAY_PARAM(all_pop_volatile_readable_flags,
2456		  all_pop_volatile_readable_flags_cases,
2457		  cs_dsp_ctl_all_param_desc);
2458
2459/*
2460 * All parameters populated, with all combinations of flags for a
2461 * volatile readable control.
2462 */
2463static const struct cs_dsp_ctl_rw_test_param all_pop_volatile_writeable_flags_cases[] = {
2464	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2465	  .flags = 0 /* flags == 0 is volatile while firmware is running */
2466	},
2467	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2468	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE,
2469	},
2470	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2471	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2472	},
2473	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2474	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2475	},
2476	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2477	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2478		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2479	},
2480};
2481KUNIT_ARRAY_PARAM(all_pop_volatile_writeable_flags,
2482		  all_pop_volatile_writeable_flags_cases,
2483		  cs_dsp_ctl_all_param_desc);
2484
2485static struct kunit_case cs_dsp_ctl_rw_test_cases_adsp[] = {
2486	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_len_gen_params),
2487	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_offset_gen_params),
2488	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_xy_gen_params),
2489	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_z_gen_params),
2490	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_alg_gen_params),
2491	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_writeable_flags_gen_params),
2492
2493	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_len_gen_params),
2494	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_offset_gen_params),
2495	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_xy_gen_params),
2496	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_z_gen_params),
2497	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running,
2498			 all_pop_volatile_readable_flags_gen_params),
2499
2500	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_started,
2501			 all_pop_volatile_readable_flags_gen_params),
2502	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped,
2503			 all_pop_volatile_readable_flags_gen_params),
2504	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped_powered_down,
2505			 all_pop_volatile_readable_flags_gen_params),
2506	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_loaded_fw,
2507			 all_pop_volatile_readable_flags_gen_params),
2508	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_running_fw,
2509			 all_pop_volatile_readable_flags_gen_params),
2510
2511	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_started,
2512			 all_pop_volatile_writeable_flags_gen_params),
2513	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped,
2514			 all_pop_volatile_writeable_flags_gen_params),
2515	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped_powered_down,
2516			 all_pop_volatile_writeable_flags_gen_params),
2517	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_loaded_fw,
2518			 all_pop_volatile_writeable_flags_gen_params),
2519	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_running_fw,
2520			 all_pop_volatile_writeable_flags_gen_params),
2521
2522	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek,
2523			 all_pop_readable_flags_gen_params),
2524	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_with_seek,
2525			 all_pop_nonvol_readable_flags_gen_params),
2526	KUNIT_CASE_PARAM(cs_dsp_ctl_read_truncated,
2527			 all_pop_readable_flags_gen_params),
2528	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_truncated,
2529			 all_pop_nonvol_readable_flags_gen_params),
2530
2531	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek,
2532			 all_pop_writeable_flags_gen_params),
2533	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_with_seek,
2534			 all_pop_nonvol_writeable_flags_gen_params),
2535	KUNIT_CASE_PARAM(cs_dsp_ctl_write_truncated,
2536			 all_pop_writeable_flags_gen_params),
2537	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_truncated,
2538			 all_pop_nonvol_writeable_flags_gen_params),
2539
2540	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_oob,
2541			 all_pop_varying_len_gen_params),
2542	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_length_overflow,
2543			 all_pop_varying_len_gen_params),
2544	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_and_length_oob,
2545			 all_pop_varying_len_gen_params),
2546	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_oob,
2547			 all_pop_varying_len_gen_params),
2548	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_length_overflow,
2549			 all_pop_varying_len_gen_params),
2550	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_and_length_oob,
2551			 all_pop_varying_len_gen_params),
2552
2553	KUNIT_CASE_PARAM(cs_dsp_ctl_read_from_writeonly,
2554			 all_pop_writeonly_flags_gen_params),
2555	KUNIT_CASE_PARAM(cs_dsp_ctl_write_to_readonly,
2556			 all_pop_readonly_flags_gen_params),
2557
2558	{ } /* terminator */
2559};
2560
2561static struct kunit_case cs_dsp_ctl_rw_test_cases_halo[] = {
2562	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_len_gen_params),
2563	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_offset_gen_params),
2564	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_xy_gen_params),
2565	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_alg_gen_params),
2566	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_writeable_flags_gen_params),
2567
2568	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_len_gen_params),
2569	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_offset_gen_params),
2570	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_xy_gen_params),
2571	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running,
2572			 all_pop_volatile_readable_flags_gen_params),
2573
2574	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_started,
2575			 all_pop_volatile_readable_flags_gen_params),
2576	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped,
2577			 all_pop_volatile_readable_flags_gen_params),
2578	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped_powered_down,
2579			 all_pop_volatile_readable_flags_gen_params),
2580	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_loaded_fw,
2581			 all_pop_volatile_readable_flags_gen_params),
2582	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_running_fw,
2583			 all_pop_volatile_readable_flags_gen_params),
2584
2585	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_started,
2586			 all_pop_volatile_writeable_flags_gen_params),
2587	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped,
2588			 all_pop_volatile_writeable_flags_gen_params),
2589	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped_powered_down,
2590			 all_pop_volatile_writeable_flags_gen_params),
2591	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_loaded_fw,
2592			 all_pop_volatile_writeable_flags_gen_params),
2593	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_running_fw,
2594			 all_pop_volatile_writeable_flags_gen_params),
2595
2596	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek,
2597			 all_pop_readable_flags_gen_params),
2598	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_with_seek,
2599			 all_pop_nonvol_readable_flags_gen_params),
2600	KUNIT_CASE_PARAM(cs_dsp_ctl_read_truncated,
2601			 all_pop_readable_flags_gen_params),
2602	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_truncated,
2603			 all_pop_nonvol_readable_flags_gen_params),
2604
2605	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek,
2606			 all_pop_writeable_flags_gen_params),
2607	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_with_seek,
2608			 all_pop_nonvol_writeable_flags_gen_params),
2609	KUNIT_CASE_PARAM(cs_dsp_ctl_write_truncated,
2610			 all_pop_writeable_flags_gen_params),
2611	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_truncated,
2612			 all_pop_nonvol_writeable_flags_gen_params),
2613
2614	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_oob,
2615			 all_pop_varying_len_gen_params),
2616	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_length_overflow,
2617			 all_pop_varying_len_gen_params),
2618	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_and_length_oob,
2619			 all_pop_varying_len_gen_params),
2620	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_oob,
2621			 all_pop_varying_len_gen_params),
2622	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_length_overflow,
2623			 all_pop_varying_len_gen_params),
2624	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_and_length_oob,
2625			 all_pop_varying_len_gen_params),
2626
2627	KUNIT_CASE_PARAM(cs_dsp_ctl_read_from_writeonly,
2628			 all_pop_writeonly_flags_gen_params),
2629	KUNIT_CASE_PARAM(cs_dsp_ctl_write_to_readonly,
2630			 all_pop_readonly_flags_gen_params),
2631
2632	{ } /* terminator */
2633};
2634
2635static struct kunit_suite cs_dsp_ctl_rw_test_halo = {
2636	.name = "cs_dsp_ctl_rw_wmfwV3_halo",
2637	.init = cs_dsp_ctl_rw_test_halo_init,
2638	.test_cases = cs_dsp_ctl_rw_test_cases_halo,
2639};
2640
2641static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1 = {
2642	.name = "cs_dsp_ctl_rw_wmfwV1_adsp2_32bit",
2643	.init = cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1_init,
2644	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2645};
2646
2647static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2 = {
2648	.name = "cs_dsp_ctl_rw_wmfwV2_adsp2_32bit",
2649	.init = cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2_init,
2650	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2651};
2652
2653static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1 = {
2654	.name = "cs_dsp_ctl_rw_wmfwV1_adsp2_16bit",
2655	.init = cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1_init,
2656	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2657};
2658
2659static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2 = {
2660	.name = "cs_dsp_ctl_rw_wmfwV2_adsp2_16bit",
2661	.init = cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2_init,
2662	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2663};
2664
2665kunit_test_suites(&cs_dsp_ctl_rw_test_halo,
2666		  &cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1,
2667		  &cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2,
2668		  &cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1,
2669		  &cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2);
~/ Read-only file preview.