File Index
Files and directories
Sign in
FILE

cs_dsp_test_bin.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/cirrus/test/cs_dsp_test_bin.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/firmware.h>
  16#include <linux/math.h>
  17#include <linux/random.h>
  18#include <linux/regmap.h>
  19
  20#include "../cs_dsp.h"
  21
  22/*
  23 * Test method is:
  24 *
  25 * 1) Create a mock regmap in cache-only mode so that all writes will be cached.
  26 * 2) Create a XM header with an algorithm list in the cached regmap.
  27 * 3) Create dummy wmfw file to satisfy cs_dsp.
  28 * 4) Create bin file content.
  29 * 5) Call cs_dsp_power_up() with the bin file.
  30 * 6) Readback the cached value of registers that should have been written and
  31 *    check they have the correct value.
  32 * 7) All the registers that are expected to have been written are dropped from
  33 *    the cache (including the XM header). This should leave the cache clean.
  34 * 8) If the cache is still dirty there have been unexpected writes.
  35 *
  36 * There are multiple different schemes used for addressing across
  37 * ADSP2 and Halo Core DSPs:
  38 *
  39 *  dsp words:	The addressing scheme used by the DSP, pointers and lengths
  40 *		in DSP memory use this. A memory region (XM, YM, ZM) is
  41 *		also required to create a unique DSP memory address.
  42 *  registers:	Addresses in the register map. Older ADSP2 devices have
  43 *		16-bit registers with an address stride of 1. Newer ADSP2
  44 *		devices have 32-bit registers with an address stride of 2.
  45 *		Halo Core devices have 32-bit registers with a stride of 4.
  46 *  unpacked:	Registers that have a 1:1 mapping to DSP words
  47 *  packed:	Registers that pack multiple DSP words more efficiently into
  48 *		multiple 32-bit registers. Because of this the relationship
  49 *		between a packed _register_ address and the corresponding
  50 *		_dsp word_ address is different from unpacked registers.
  51 *		Packed registers can only be accessed as a group of
  52 *		multiple registers, therefore can only read/write a group
  53 *		of multiple DSP words.
  54 *		Packed registers only exist on Halo Core DSPs.
  55 *
  56 * Addresses can also be relative to the start of an algorithm, and this
  57 * can be expressed in dsp words, register addresses, or bytes.
  58 */
  59
  60KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)
  61KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)
  62
  63struct cs_dsp_test_local {
  64	struct cs_dsp_mock_bin_builder *bin_builder;
  65	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
  66	struct firmware *wmfw;
  67};
  68
  69struct bin_test_param {
  70	const char *name;
  71	int mem_type;
  72	unsigned int offset_words;
  73	int alg_idx;
  74};
  75
  76static const struct cs_dsp_mock_alg_def bin_test_mock_algs[] = {
  77	{
  78		.id = 0xfafa,
  79		.ver = 0x100000,
  80		.xm_size_words = 164,
  81		.ym_size_words = 164,
  82		.zm_size_words = 164,
  83	},
  84	{
  85		.id = 0xfbfb,
  86		.ver = 0x100000,
  87		.xm_size_words = 99,
  88		.ym_size_words = 99,
  89		.zm_size_words = 99,
  90	},
  91	{
  92		.id = 0xc321,
  93		.ver = 0x100000,
  94		.xm_size_words = 120,
  95		.ym_size_words = 120,
  96		.zm_size_words = 120,
  97	},
  98	{
  99		.id = 0xb123,
 100		.ver = 0x100000,
 101		.xm_size_words = 96,
 102		.ym_size_words = 96,
 103		.zm_size_words = 96,
 104	},
 105};
 106
 107/*
 108 * Convert number of DSP words to number of packed registers rounded
 109 * down to the nearest register.
 110 * There are 3 registers for every 4 packed words.
 111 */
 112static unsigned int _num_words_to_num_packed_regs(unsigned int num_dsp_words)
 113{
 114	return (num_dsp_words * 3) / 4;
 115}
 116
 117/* bin file that patches a single DSP word */
 118static void bin_patch_one_word(struct kunit *test)
 119{
 120	struct cs_dsp_test *priv = test->priv;
 121	const struct bin_test_param *param = test->param_value;
 122	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 123	u32 reg_val, payload_data;
 124	unsigned int alg_base_words, reg_addr;
 125	struct firmware *fw;
 126
 127	get_random_bytes(&payload_data, sizeof(payload_data));
 128
 129	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 130							bin_test_mock_algs[param->alg_idx].id,
 131							param->mem_type);
 132
 133	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 134				  bin_test_mock_algs[param->alg_idx].id,
 135				  bin_test_mock_algs[param->alg_idx].ver,
 136				  param->mem_type,
 137				  param->offset_words * reg_inc_per_word,
 138				  &payload_data, sizeof(payload_data));
 139
 140	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 141	KUNIT_ASSERT_EQ(test,
 142			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 143					fw, "mock_bin", "misc"),
 144			0);
 145
 146	/* Content of registers should match payload_data */
 147	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 148		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
 149	reg_val = 0;
 150	KUNIT_EXPECT_EQ(test,
 151			regmap_raw_read(priv->dsp->regmap, reg_addr,
 152					&reg_val, sizeof(reg_val)),
 153			0);
 154	KUNIT_EXPECT_EQ(test, reg_val, payload_data);
 155
 156	/* Drop expected writes and the cache should then be clean */
 157	cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 158	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 159
 160	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 161}
 162
 163/* bin file with a single payload that patches consecutive words */
 164static void bin_patch_one_multiword(struct kunit *test)
 165{
 166	struct cs_dsp_test *priv = test->priv;
 167	const struct bin_test_param *param = test->param_value;
 168	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 169	u32 payload_data[16], readback[16];
 170	unsigned int alg_base_words, reg_addr;
 171	struct firmware *fw;
 172
 173	static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));
 174
 175	get_random_bytes(&payload_data, sizeof(payload_data));
 176	memset(readback, 0, sizeof(readback));
 177
 178	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 179							bin_test_mock_algs[param->alg_idx].id,
 180							param->mem_type);
 181
 182	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 183				  bin_test_mock_algs[param->alg_idx].id,
 184				  bin_test_mock_algs[param->alg_idx].ver,
 185				  param->mem_type,
 186				  param->offset_words * reg_inc_per_word,
 187				  payload_data, sizeof(payload_data));
 188
 189	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 190	KUNIT_ASSERT_EQ(test,
 191			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 192					fw, "mock_bin", "misc"),
 193			0);
 194
 195	/* Content of registers should match payload_data */
 196	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 197		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
 198	KUNIT_EXPECT_EQ(test,
 199			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
 200					sizeof(readback)),
 201			0);
 202	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
 203
 204	/* Drop expected writes and the cache should then be clean */
 205	cs_dsp_mock_regmap_drop_range(priv, reg_addr,
 206				      reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
 207	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 208	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 209}
 210
 211/* bin file with a multiple one-word payloads that patch consecutive words */
 212static void bin_patch_multi_oneword(struct kunit *test)
 213{
 214	struct cs_dsp_test *priv = test->priv;
 215	const struct bin_test_param *param = test->param_value;
 216	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 217	u32 payload_data[16], readback[16];
 218	unsigned int alg_base_words, reg_addr;
 219	struct firmware *fw;
 220	int i;
 221
 222	static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));
 223
 224	get_random_bytes(&payload_data, sizeof(payload_data));
 225	memset(readback, 0, sizeof(readback));
 226
 227	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 228							bin_test_mock_algs[param->alg_idx].id,
 229							param->mem_type);
 230
 231	/* Add one payload per word */
 232	for (i = 0; i < ARRAY_SIZE(payload_data); ++i) {
 233		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 234					  bin_test_mock_algs[param->alg_idx].id,
 235					  bin_test_mock_algs[param->alg_idx].ver,
 236					  param->mem_type,
 237					  (param->offset_words + i) * reg_inc_per_word,
 238					  &payload_data[i], sizeof(payload_data[i]));
 239	}
 240
 241	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 242	KUNIT_ASSERT_EQ(test,
 243			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 244					fw, "mock_bin", "misc"),
 245			 0);
 246
 247	/* Content of registers should match payload_data */
 248	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 249		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
 250	KUNIT_EXPECT_EQ(test,
 251			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
 252					sizeof(readback)),
 253			0);
 254	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
 255
 256	/* Drop expected writes and the cache should then be clean */
 257	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 258	cs_dsp_mock_regmap_drop_range(priv, reg_addr,
 259				      reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
 260	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 261}
 262
 263/*
 264 * bin file with a multiple one-word payloads that patch a block of consecutive
 265 * words but the payloads are not in address order.
 266 */
 267static void bin_patch_multi_oneword_unordered(struct kunit *test)
 268{
 269	struct cs_dsp_test *priv = test->priv;
 270	const struct bin_test_param *param = test->param_value;
 271	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 272	u32 payload_data[16], readback[16];
 273	static const u8 word_order[] = { 10, 2, 12, 4, 0, 11, 6, 1, 3, 15, 5, 13, 8, 7, 9, 14 };
 274	unsigned int alg_base_words, reg_addr;
 275	struct firmware *fw;
 276	int i;
 277
 278	static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));
 279	static_assert(ARRAY_SIZE(word_order) == ARRAY_SIZE(payload_data));
 280
 281	get_random_bytes(&payload_data, sizeof(payload_data));
 282	memset(readback, 0, sizeof(readback));
 283
 284	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 285							bin_test_mock_algs[param->alg_idx].id,
 286							param->mem_type);
 287
 288	/* Add one payload per word */
 289	for (i = 0; i < ARRAY_SIZE(word_order); ++i) {
 290		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 291					  bin_test_mock_algs[param->alg_idx].id,
 292					  bin_test_mock_algs[param->alg_idx].ver,
 293					  param->mem_type,
 294					  (param->offset_words + word_order[i]) *
 295					  reg_inc_per_word,
 296					  &payload_data[word_order[i]], sizeof(payload_data[0]));
 297	}
 298
 299	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 300	KUNIT_ASSERT_EQ(test,
 301			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 302					fw, "mock_bin", "misc"),
 303			0);
 304
 305	/* Content of registers should match payload_data */
 306	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 307		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
 308	KUNIT_EXPECT_EQ(test,
 309			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
 310					sizeof(readback)),
 311			0);
 312	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
 313
 314	/* Drop expected writes and the cache should then be clean */
 315	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 316	cs_dsp_mock_regmap_drop_range(priv, reg_addr,
 317				      reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
 318	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 319}
 320
 321/*
 322 * bin file with a multiple one-word payloads. The payloads are not in address
 323 * order and collectively do not patch a contiguous block of memory.
 324 */
 325static void bin_patch_multi_oneword_sparse_unordered(struct kunit *test)
 326{
 327	struct cs_dsp_test *priv = test->priv;
 328	const struct bin_test_param *param = test->param_value;
 329	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 330	static const u8 word_offsets[] = {
 331		11, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,
 332		54, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,
 333		29, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22
 334	};
 335	u32 payload_data[44];
 336	unsigned int alg_base_words, reg_addr;
 337	struct firmware *fw;
 338	u32 reg_val;
 339	int i;
 340
 341	static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(payload_data));
 342
 343	get_random_bytes(&payload_data, sizeof(payload_data));
 344
 345	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 346							bin_test_mock_algs[param->alg_idx].id,
 347							param->mem_type);
 348
 349	/* Add one payload per word */
 350	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
 351		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 352					  bin_test_mock_algs[param->alg_idx].id,
 353					  bin_test_mock_algs[param->alg_idx].ver,
 354					  param->mem_type,
 355					  word_offsets[i] * reg_inc_per_word,
 356					  &payload_data[i], sizeof(payload_data[i]));
 357	}
 358
 359	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 360	KUNIT_ASSERT_EQ(test,
 361			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 362					fw, "mock_bin", "misc"),
 363			0);
 364
 365	/* Content of registers should match payload_data */
 366	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
 367		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 368			   ((alg_base_words + word_offsets[i]) * reg_inc_per_word);
 369		reg_val = 0;
 370		KUNIT_EXPECT_EQ(test,
 371				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
 372						sizeof(reg_val)),
 373				0);
 374		KUNIT_EXPECT_MEMEQ(test, &reg_val, &payload_data[i], sizeof(reg_val));
 375
 376		/* Drop expected writes from the cache */
 377		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 378	}
 379
 380	/* Drop expected writes and the cache should then be clean */
 381	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 382	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 383}
 384
 385/*
 386 * bin file that patches a single DSP word in each of the memory regions
 387 * of one algorithm.
 388 */
 389static void bin_patch_one_word_multiple_mems(struct kunit *test)
 390{
 391	struct cs_dsp_test *priv = test->priv;
 392	const struct bin_test_param *param = test->param_value;
 393	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 394	unsigned int alg_xm_base_words, alg_ym_base_words, alg_zm_base_words;
 395	unsigned int reg_addr;
 396	u32 payload_data[3];
 397	struct firmware *fw;
 398	u32 reg_val;
 399
 400	get_random_bytes(&payload_data, sizeof(payload_data));
 401
 402	alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 403							bin_test_mock_algs[param->alg_idx].id,
 404							WMFW_ADSP2_XM);
 405	alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 406							bin_test_mock_algs[param->alg_idx].id,
 407							WMFW_ADSP2_YM);
 408
 409	if (cs_dsp_mock_has_zm(priv)) {
 410		alg_zm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 411							bin_test_mock_algs[param->alg_idx].id,
 412							WMFW_ADSP2_ZM);
 413	} else {
 414		alg_zm_base_words = 0;
 415	}
 416
 417	/* Add words to XM, YM and ZM */
 418	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 419				  bin_test_mock_algs[param->alg_idx].id,
 420				  bin_test_mock_algs[param->alg_idx].ver,
 421				  WMFW_ADSP2_XM,
 422				  param->offset_words * reg_inc_per_word,
 423				  &payload_data[0], sizeof(payload_data[0]));
 424
 425	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 426				  bin_test_mock_algs[param->alg_idx].id,
 427				  bin_test_mock_algs[param->alg_idx].ver,
 428				  WMFW_ADSP2_YM,
 429				  param->offset_words * reg_inc_per_word,
 430				  &payload_data[1], sizeof(payload_data[1]));
 431
 432	if (cs_dsp_mock_has_zm(priv)) {
 433		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 434					  bin_test_mock_algs[param->alg_idx].id,
 435					  bin_test_mock_algs[param->alg_idx].ver,
 436					  WMFW_ADSP2_ZM,
 437					  param->offset_words * reg_inc_per_word,
 438					  &payload_data[2], sizeof(payload_data[2]));
 439	}
 440
 441	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 442	KUNIT_ASSERT_EQ(test,
 443			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 444					fw, "mock_bin", "misc"),
 445			0);
 446
 447	/* Content of registers should match payload_data */
 448	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM) +
 449		   ((alg_xm_base_words + param->offset_words) * reg_inc_per_word);
 450	reg_val = 0;
 451	KUNIT_EXPECT_EQ(test,
 452			regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val, sizeof(reg_val)),
 453			0);
 454	KUNIT_EXPECT_EQ(test, reg_val, payload_data[0]);
 455
 456	cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 457
 458	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM) +
 459		   ((alg_ym_base_words + param->offset_words) * reg_inc_per_word);
 460	reg_val = 0;
 461	KUNIT_EXPECT_EQ(test,
 462			regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val, sizeof(reg_val)),
 463			0);
 464	KUNIT_EXPECT_EQ(test, reg_val, payload_data[1]);
 465
 466	cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 467
 468	if (cs_dsp_mock_has_zm(priv)) {
 469		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM) +
 470			   ((alg_zm_base_words + param->offset_words) * reg_inc_per_word);
 471		reg_val = 0;
 472		KUNIT_EXPECT_EQ(test,
 473				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
 474						sizeof(reg_val)),
 475				0);
 476		KUNIT_EXPECT_EQ(test, reg_val, payload_data[2]);
 477
 478		/* Drop expected writes from the cache */
 479		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 480	}
 481
 482	/* Drop expected writes and the cache should then be clean */
 483	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 484	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 485}
 486
 487/*
 488 * bin file that patches a single DSP word in multiple algorithms.
 489 */
 490static void bin_patch_one_word_multiple_algs(struct kunit *test)
 491{
 492	struct cs_dsp_test *priv = test->priv;
 493	const struct bin_test_param *param = test->param_value;
 494	u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];
 495	unsigned int alg_base_words;
 496	unsigned int reg_inc_per_word, reg_addr;
 497	struct firmware *fw;
 498	u32 reg_val;
 499	int i;
 500
 501	get_random_bytes(&payload_data, sizeof(payload_data));
 502
 503	/* Add one payload per algorithm */
 504	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
 505		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 506
 507		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 508					  bin_test_mock_algs[i].id,
 509					  bin_test_mock_algs[i].ver,
 510					  param->mem_type,
 511					  param->offset_words * reg_inc_per_word,
 512					  &payload_data[i], sizeof(payload_data[i]));
 513	}
 514
 515	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 516	KUNIT_ASSERT_EQ(test,
 517			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 518					fw, "mock_bin", "misc"),
 519			0);
 520
 521	/* Content of registers should match payload_data */
 522	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
 523		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 524								bin_test_mock_algs[i].id,
 525								param->mem_type);
 526		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 527		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 528			   ((alg_base_words + param->offset_words) * reg_inc_per_word);
 529		reg_val = 0;
 530		KUNIT_EXPECT_EQ(test,
 531				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
 532						sizeof(reg_val)),
 533				0);
 534		KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);
 535
 536		/* Drop expected writes from the cache */
 537		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 538	}
 539
 540	/* Drop expected writes and the cache should then be clean */
 541	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 542	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 543}
 544
 545/*
 546 * bin file that patches a single DSP word in multiple algorithms.
 547 * The algorithms are not patched in the same order they appear in the XM header.
 548 */
 549static void bin_patch_one_word_multiple_algs_unordered(struct kunit *test)
 550{
 551	struct cs_dsp_test *priv = test->priv;
 552	const struct bin_test_param *param = test->param_value;
 553	static const u8 alg_order[] = { 3, 0, 2, 1 };
 554	u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];
 555	unsigned int alg_base_words;
 556	unsigned int reg_inc_per_word, reg_addr;
 557	struct firmware *fw;
 558	u32 reg_val;
 559	int i, alg_idx;
 560
 561	static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));
 562
 563	get_random_bytes(&payload_data, sizeof(payload_data));
 564
 565	/* Add one payload per algorithm */
 566	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
 567		alg_idx = alg_order[i];
 568		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 569
 570		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 571					  bin_test_mock_algs[alg_idx].id,
 572					  bin_test_mock_algs[alg_idx].ver,
 573					  param->mem_type,
 574					  param->offset_words * reg_inc_per_word,
 575					  &payload_data[i], sizeof(payload_data[i]));
 576	}
 577
 578	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 579	KUNIT_ASSERT_EQ(test,
 580			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 581					fw, "mock_bin", "misc"),
 582			0);
 583
 584	/* Content of registers should match payload_data */
 585	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
 586		alg_idx = alg_order[i];
 587		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 588								bin_test_mock_algs[alg_idx].id,
 589								param->mem_type);
 590		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
 591		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 592			   ((alg_base_words + param->offset_words) * reg_inc_per_word);
 593		reg_val = 0;
 594		KUNIT_EXPECT_EQ(test,
 595				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
 596						sizeof(reg_val)),
 597				0);
 598		KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);
 599
 600		/* Drop expected writes from the cache */
 601		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
 602	}
 603
 604	/* Drop expected writes and the cache should then be clean */
 605	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 606	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 607}
 608
 609/* bin file that patches a single packed block of DSP words */
 610static void bin_patch_1_packed(struct kunit *test)
 611{
 612	struct cs_dsp_test *priv = test->priv;
 613	const struct bin_test_param *param = test->param_value;
 614	u32 packed_payload[3], readback[3];
 615	unsigned int alg_base_words, patch_pos_words;
 616	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
 617	unsigned int reg_addr;
 618	struct firmware *fw;
 619
 620	static_assert(sizeof(readback) == sizeof(packed_payload));
 621
 622	get_random_bytes(packed_payload, sizeof(packed_payload));
 623
 624	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 625							bin_test_mock_algs[param->alg_idx].id,
 626							param->mem_type);
 627	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
 628
 629	/* Round patch start word up to a packed boundary */
 630	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
 631	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
 632
 633	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 634				  bin_test_mock_algs[param->alg_idx].id,
 635				  bin_test_mock_algs[param->alg_idx].ver,
 636				  param->mem_type,
 637				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
 638				  packed_payload, sizeof(packed_payload));
 639
 640	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 641	KUNIT_ASSERT_EQ(test,
 642			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 643					fw, "mock_bin", "misc"),
 644			0);
 645
 646	/* Content of registers should match payload_data */
 647	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 648		   (patch_pos_in_packed_regs * 4);
 649	memset(readback, 0, sizeof(readback));
 650	KUNIT_EXPECT_EQ(test,
 651			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
 652					sizeof(readback)),
 653			0);
 654	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
 655
 656	/* Drop expected writes and the cache should then be clean */
 657	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 658	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
 659	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 660}
 661
 662/*
 663 * Patch data that is one word longer than a packed block using one
 664 * packed block followed by one unpacked word.
 665 */
 666static void bin_patch_1_packed_1_single_trailing(struct kunit *test)
 667{
 668	struct cs_dsp_test *priv = test->priv;
 669	const struct bin_test_param *param = test->param_value;
 670	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
 671	u32 packed_payload[3], unpacked_payload[1], readback[3];
 672	unsigned int alg_base_words, patch_pos_words;
 673	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
 674	unsigned int reg_addr;
 675	struct firmware *fw;
 676
 677	static_assert(sizeof(readback) == sizeof(packed_payload));
 678	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
 679
 680	get_random_bytes(packed_payload, sizeof(packed_payload));
 681	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
 682
 683	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 684							bin_test_mock_algs[param->alg_idx].id,
 685							param->mem_type);
 686	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
 687
 688	/* Round patch start word up to a packed boundary */
 689	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
 690	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
 691
 692	/* Patch packed block */
 693	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 694				  bin_test_mock_algs[param->alg_idx].id,
 695				  bin_test_mock_algs[param->alg_idx].ver,
 696				  param->mem_type,
 697				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
 698				  &packed_payload, sizeof(packed_payload));
 699
 700	/* ... and the unpacked word following that */
 701	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 702				  bin_test_mock_algs[param->alg_idx].id,
 703				  bin_test_mock_algs[param->alg_idx].ver,
 704				  unpacked_mem_type,
 705				  ((patch_pos_words + 4) - alg_base_words) * 4,
 706				  unpacked_payload, sizeof(unpacked_payload));
 707
 708	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 709	KUNIT_ASSERT_EQ(test,
 710			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 711					fw, "mock_bin", "misc"),
 712			0);
 713
 714	/* Content of packed registers should match packed_payload */
 715	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 716		   (patch_pos_in_packed_regs * 4);
 717	memset(readback, 0, sizeof(readback));
 718	KUNIT_EXPECT_EQ(test,
 719			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
 720			0);
 721	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
 722
 723	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
 724
 725	/* Content of unpacked registers should match unpacked_payload */
 726	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
 727		   (patch_pos_words + 4) * 4;
 728	memset(readback, 0, sizeof(readback));
 729	KUNIT_EXPECT_EQ(test,
 730			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
 731					sizeof(unpacked_payload)),
 732			0);
 733	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
 734
 735	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
 736
 737	/* Drop expected writes and the cache should then be clean */
 738	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 739	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 740}
 741
 742/*
 743 * Patch data that is two words longer than a packed block using one
 744 * packed block followed by two blocks of one unpacked word.
 745 */
 746static void bin_patch_1_packed_2_single_trailing(struct kunit *test)
 747{
 748	struct cs_dsp_test *priv = test->priv;
 749	const struct bin_test_param *param = test->param_value;
 750	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
 751	u32 packed_payload[3], unpacked_payloads[2], readback[3];
 752	unsigned int alg_base_words, patch_pos_words;
 753	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
 754	unsigned int reg_addr;
 755	struct firmware *fw;
 756
 757	static_assert(sizeof(readback) == sizeof(packed_payload));
 758	static_assert(sizeof(readback) >= sizeof(unpacked_payloads));
 759
 760	get_random_bytes(packed_payload, sizeof(packed_payload));
 761	get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));
 762
 763	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 764							bin_test_mock_algs[param->alg_idx].id,
 765							param->mem_type);
 766	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
 767
 768	/* Round patch start word up to a packed boundary */
 769	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
 770	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
 771
 772	/* Patch packed block */
 773	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 774				  bin_test_mock_algs[param->alg_idx].id,
 775				  bin_test_mock_algs[param->alg_idx].ver,
 776				  param->mem_type,
 777				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
 778				  &packed_payload, sizeof(packed_payload));
 779
 780	/* ... and the unpacked words following that */
 781	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 782				  bin_test_mock_algs[param->alg_idx].id,
 783				  bin_test_mock_algs[param->alg_idx].ver,
 784				  unpacked_mem_type,
 785				  ((patch_pos_words + 4) - alg_base_words) * 4,
 786				  &unpacked_payloads[0], sizeof(unpacked_payloads[0]));
 787
 788	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 789				  bin_test_mock_algs[param->alg_idx].id,
 790				  bin_test_mock_algs[param->alg_idx].ver,
 791				  unpacked_mem_type,
 792				  ((patch_pos_words + 5) - alg_base_words) * 4,
 793				  &unpacked_payloads[1], sizeof(unpacked_payloads[1]));
 794
 795	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 796	KUNIT_ASSERT_EQ(test,
 797			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 798					fw, "mock_bin", "misc"),
 799			0);
 800
 801	/* Content of packed registers should match packed_payload */
 802	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 803		   (patch_pos_in_packed_regs * 4);
 804	memset(readback, 0, sizeof(readback));
 805	KUNIT_EXPECT_EQ(test,
 806			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
 807			0);
 808	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
 809
 810	/* Drop expected writes from the cache */
 811	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
 812
 813	/* Content of unpacked registers should match unpacked_payloads */
 814	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
 815		   (patch_pos_words + 4) * 4;
 816	memset(readback, 0, sizeof(readback));
 817	KUNIT_EXPECT_EQ(test,
 818			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
 819					sizeof(unpacked_payloads)),
 820			0);
 821	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));
 822
 823	/* Drop expected writes from the cache */
 824	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));
 825
 826	/* Drop expected writes and the cache should then be clean */
 827	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 828	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 829}
 830
 831/*
 832 * Patch data that is three words longer than a packed block using one
 833 * packed block followed by three blocks of one unpacked word.
 834 */
 835static void bin_patch_1_packed_3_single_trailing(struct kunit *test)
 836{
 837	struct cs_dsp_test *priv = test->priv;
 838	const struct bin_test_param *param = test->param_value;
 839	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
 840	u32 packed_payload[3], unpacked_payloads[3], readback[3];
 841	unsigned int alg_base_words, patch_pos_words;
 842	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
 843	unsigned int reg_addr;
 844	struct firmware *fw;
 845
 846	static_assert(sizeof(readback) == sizeof(packed_payload));
 847	static_assert(sizeof(readback) >= sizeof(unpacked_payloads));
 848
 849	get_random_bytes(packed_payload, sizeof(packed_payload));
 850	get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));
 851
 852	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 853							bin_test_mock_algs[param->alg_idx].id,
 854							param->mem_type);
 855	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
 856
 857	/* Round patch start word up to a packed boundary */
 858	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
 859	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
 860
 861	/* Patch packed block */
 862	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 863				  bin_test_mock_algs[param->alg_idx].id,
 864				  bin_test_mock_algs[param->alg_idx].ver,
 865				  param->mem_type,
 866				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
 867				  &packed_payload, sizeof(packed_payload));
 868
 869	/* ... and the unpacked words following that */
 870	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 871				  bin_test_mock_algs[param->alg_idx].id,
 872				  bin_test_mock_algs[param->alg_idx].ver,
 873				  unpacked_mem_type,
 874				  ((patch_pos_words + 4) - alg_base_words) * 4,
 875				  &unpacked_payloads[0], sizeof(unpacked_payloads[0]));
 876
 877	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 878				  bin_test_mock_algs[param->alg_idx].id,
 879				  bin_test_mock_algs[param->alg_idx].ver,
 880				  unpacked_mem_type,
 881				  ((patch_pos_words + 5) - alg_base_words) * 4,
 882				  &unpacked_payloads[1], sizeof(unpacked_payloads[1]));
 883
 884	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 885				  bin_test_mock_algs[param->alg_idx].id,
 886				  bin_test_mock_algs[param->alg_idx].ver,
 887				  unpacked_mem_type,
 888				  ((patch_pos_words + 6) - alg_base_words) * 4,
 889				  &unpacked_payloads[2], sizeof(unpacked_payloads[2]));
 890
 891	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 892	KUNIT_ASSERT_EQ(test,
 893			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 894					fw, "mock_bin", "misc"),
 895			0);
 896
 897	/* Content of packed registers should match packed_payload */
 898	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 899		   (patch_pos_in_packed_regs * 4);
 900	memset(readback, 0, sizeof(readback));
 901	KUNIT_EXPECT_EQ(test,
 902			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
 903			0);
 904	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
 905
 906	/* Drop expected writes from the cache */
 907	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
 908
 909	/* Content of unpacked registers should match unpacked_payloads */
 910	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
 911		   (patch_pos_words + 4) * 4;
 912	memset(readback, 0, sizeof(readback));
 913	KUNIT_EXPECT_EQ(test,
 914			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
 915					sizeof(unpacked_payloads)),
 916			0);
 917	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));
 918
 919	/* Drop expected writes from the cache */
 920	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));
 921
 922	/* Drop expected writes and the cache should then be clean */
 923	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
 924	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
 925}
 926
 927/*
 928 * Patch data that is two words longer than a packed block using one
 929 * packed block followed by a block of two unpacked words.
 930 */
 931static void bin_patch_1_packed_2_trailing(struct kunit *test)
 932{
 933	struct cs_dsp_test *priv = test->priv;
 934	const struct bin_test_param *param = test->param_value;
 935	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
 936	u32 packed_payload[3], unpacked_payload[2], readback[3];
 937	unsigned int alg_base_words, patch_pos_words;
 938	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
 939	unsigned int reg_addr;
 940	struct firmware *fw;
 941
 942	static_assert(sizeof(readback) == sizeof(packed_payload));
 943	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
 944
 945	get_random_bytes(packed_payload, sizeof(packed_payload));
 946	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
 947
 948	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
 949							bin_test_mock_algs[param->alg_idx].id,
 950							param->mem_type);
 951	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
 952
 953	/* Round patch start word up to a packed boundary */
 954	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
 955	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
 956
 957	/* Patch packed block */
 958	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 959				  bin_test_mock_algs[param->alg_idx].id,
 960				  bin_test_mock_algs[param->alg_idx].ver,
 961				  param->mem_type,
 962				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
 963				  &packed_payload, sizeof(packed_payload));
 964
 965	/* ... and the unpacked words following that */
 966	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
 967				  bin_test_mock_algs[param->alg_idx].id,
 968				  bin_test_mock_algs[param->alg_idx].ver,
 969				  unpacked_mem_type,
 970				  ((patch_pos_words + 4) - alg_base_words) * 4,
 971				  unpacked_payload, sizeof(unpacked_payload));
 972
 973	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
 974	KUNIT_ASSERT_EQ(test,
 975			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
 976					fw, "mock_bin", "misc"),
 977			0);
 978
 979	/* Content of packed registers should match packed_payload */
 980	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
 981		   (patch_pos_in_packed_regs * 4);
 982	memset(readback, 0, sizeof(readback));
 983	KUNIT_EXPECT_EQ(test,
 984			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
 985			0);
 986	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
 987
 988	/* Drop expected writes from the cache */
 989	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
 990
 991	/* Content of unpacked registers should match unpacked_payload */
 992	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
 993		   (patch_pos_words + 4) * 4;
 994	memset(readback, 0, sizeof(readback));
 995	KUNIT_EXPECT_EQ(test,
 996			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
 997					sizeof(unpacked_payload)),
 998			0);
 999	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1000
1001	/* Drop expected writes from the cache */
1002	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1003
1004	/* Drop expected writes and the cache should then be clean */
1005	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1006	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1007}
1008
1009/*
1010 * Patch data that is three words longer than a packed block using one
1011 * packed block followed by a block of three unpacked words.
1012 */
1013static void bin_patch_1_packed_3_trailing(struct kunit *test)
1014{
1015	struct cs_dsp_test *priv = test->priv;
1016	const struct bin_test_param *param = test->param_value;
1017	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1018	u32 packed_payload[3], unpacked_payload[3], readback[3];
1019	unsigned int alg_base_words, patch_pos_words;
1020	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1021	unsigned int reg_addr;
1022	struct firmware *fw;
1023
1024	static_assert(sizeof(readback) == sizeof(packed_payload));
1025	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1026
1027	get_random_bytes(packed_payload, sizeof(packed_payload));
1028	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1029
1030	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1031							bin_test_mock_algs[param->alg_idx].id,
1032							param->mem_type);
1033	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1034
1035	/* Round patch start word up to a packed boundary */
1036	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1037	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1038
1039	/* Patch packed block */
1040	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1041				  bin_test_mock_algs[param->alg_idx].id,
1042				  bin_test_mock_algs[param->alg_idx].ver,
1043				  param->mem_type,
1044				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1045				  &packed_payload, sizeof(packed_payload));
1046
1047	/* ... and the unpacked words following that */
1048	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1049				  bin_test_mock_algs[param->alg_idx].id,
1050				  bin_test_mock_algs[param->alg_idx].ver,
1051				  unpacked_mem_type,
1052				  ((patch_pos_words + 4) - alg_base_words) * 4,
1053				  unpacked_payload, sizeof(unpacked_payload));
1054
1055	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1056	KUNIT_ASSERT_EQ(test,
1057			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1058					fw, "mock_bin", "misc"),
1059			0);
1060
1061	/* Content of packed registers should match packed_payload */
1062	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1063		   (patch_pos_in_packed_regs * 4);
1064	memset(readback, 0, sizeof(readback));
1065	KUNIT_EXPECT_EQ(test,
1066			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1067			0);
1068	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1069
1070	/* Drop expected writes from the cache */
1071	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1072
1073	/* Content of unpacked registers should match unpacked_payload */
1074	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1075		   (patch_pos_words + 4) * 4;
1076	memset(readback, 0, sizeof(readback));
1077	KUNIT_EXPECT_EQ(test,
1078			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1079					sizeof(unpacked_payload)),
1080			0);
1081	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1082
1083	/* Drop expected writes from the cache */
1084	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1085
1086	/* Drop expected writes and the cache should then be clean */
1087	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1088	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1089}
1090
1091/*
1092 * Patch data that starts one word before a packed boundary using one
1093 * unpacked word followed by one packed block.
1094 */
1095static void bin_patch_1_single_leading_1_packed(struct kunit *test)
1096{
1097	struct cs_dsp_test *priv = test->priv;
1098	const struct bin_test_param *param = test->param_value;
1099	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1100	u32 packed_payload[3], unpacked_payload[1], readback[3];
1101	unsigned int alg_base_words, packed_patch_pos_words;
1102	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1103	unsigned int reg_addr;
1104	struct firmware *fw;
1105
1106	static_assert(sizeof(readback) == sizeof(packed_payload));
1107	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1108
1109	get_random_bytes(packed_payload, sizeof(packed_payload));
1110	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1111	memset(readback, 0, sizeof(readback));
1112
1113	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1114							bin_test_mock_algs[param->alg_idx].id,
1115							param->mem_type);
1116	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1117
1118	/* Round packed start word up to a packed boundary and move to the next boundary */
1119	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1120
1121	/* Patch the leading unpacked word */
1122	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1123				  bin_test_mock_algs[param->alg_idx].id,
1124				  bin_test_mock_algs[param->alg_idx].ver,
1125				  unpacked_mem_type,
1126				  ((packed_patch_pos_words - 1) - alg_base_words) * 4,
1127				  unpacked_payload, sizeof(unpacked_payload));
1128	/* ... then the packed block */
1129	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1130	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1131				  bin_test_mock_algs[param->alg_idx].id,
1132				  bin_test_mock_algs[param->alg_idx].ver,
1133				  param->mem_type,
1134				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1135				  &packed_payload, sizeof(packed_payload));
1136
1137	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1138	KUNIT_ASSERT_EQ(test,
1139			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1140					fw, "mock_bin", "misc"),
1141			0);
1142
1143	/* Content of packed registers should match packed_payload */
1144	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1145		   (patch_pos_in_packed_regs * 4);
1146	KUNIT_EXPECT_EQ(test,
1147			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1148			0);
1149	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1150
1151	/* Drop expected writes from the cache */
1152	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1153
1154	/* Content of unpacked registers should match unpacked_payload */
1155	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1156		   (packed_patch_pos_words - 1) * 4;
1157	KUNIT_EXPECT_EQ(test,
1158			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1159					sizeof(unpacked_payload)),
1160			0);
1161	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1162
1163	/* Drop expected writes from the cache */
1164	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1165
1166	/* Drop expected writes and the cache should then be clean */
1167	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1168	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1169}
1170
1171/*
1172 * Patch data that starts two words before a packed boundary using two
1173 * unpacked words followed by one packed block.
1174 */
1175static void bin_patch_2_single_leading_1_packed(struct kunit *test)
1176{
1177	struct cs_dsp_test *priv = test->priv;
1178	const struct bin_test_param *param = test->param_value;
1179	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1180	u32 packed_payload[3], unpacked_payload[2], readback[3];
1181	unsigned int alg_base_words, packed_patch_pos_words;
1182	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1183	unsigned int reg_addr;
1184	struct firmware *fw;
1185
1186	static_assert(sizeof(readback) == sizeof(packed_payload));
1187	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1188
1189	get_random_bytes(packed_payload, sizeof(packed_payload));
1190	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1191
1192	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1193							bin_test_mock_algs[param->alg_idx].id,
1194							param->mem_type);
1195	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1196
1197	/* Round packed start word up to a packed boundary and move to the next boundary */
1198	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1199
1200	/* Patch the leading unpacked words */
1201	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1202				  bin_test_mock_algs[param->alg_idx].id,
1203				  bin_test_mock_algs[param->alg_idx].ver,
1204				  unpacked_mem_type,
1205				  ((packed_patch_pos_words - 2) - alg_base_words) * 4,
1206				  &unpacked_payload[0], sizeof(unpacked_payload[0]));
1207	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1208				  bin_test_mock_algs[param->alg_idx].id,
1209				  bin_test_mock_algs[param->alg_idx].ver,
1210				  unpacked_mem_type,
1211				  ((packed_patch_pos_words - 1) - alg_base_words) * 4,
1212				  &unpacked_payload[1], sizeof(unpacked_payload[1]));
1213	/* ... then the packed block */
1214	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1215	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1216				  bin_test_mock_algs[param->alg_idx].id,
1217				  bin_test_mock_algs[param->alg_idx].ver,
1218				  param->mem_type,
1219				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1220				  &packed_payload, sizeof(packed_payload));
1221
1222	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1223	KUNIT_ASSERT_EQ(test,
1224			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1225					fw, "mock_bin", "misc"),
1226			0);
1227
1228	/* Content of packed registers should match packed_payload */
1229	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1230		   (patch_pos_in_packed_regs * 4);
1231	memset(readback, 0, sizeof(readback));
1232	KUNIT_EXPECT_EQ(test,
1233			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1234			0);
1235	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1236
1237	/* Drop expected writes from the cache */
1238	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1239
1240	/* Content of unpacked registers should match unpacked_payload */
1241	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1242		   (packed_patch_pos_words - 2) * 4;
1243	memset(readback, 0, sizeof(readback));
1244	KUNIT_EXPECT_EQ(test,
1245			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1246					sizeof(unpacked_payload)),
1247			0);
1248	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1249
1250	/* Drop expected writes from the cache */
1251	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1252
1253	/* Drop expected writes and the cache should then be clean */
1254	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1255	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1256}
1257
1258/*
1259 * Patch data that starts two words before a packed boundary using one
1260 * block of two unpacked words followed by one packed block.
1261 */
1262static void bin_patch_2_leading_1_packed(struct kunit *test)
1263{
1264	struct cs_dsp_test *priv = test->priv;
1265	const struct bin_test_param *param = test->param_value;
1266	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1267	u32 packed_payload[3], unpacked_payload[2], readback[3];
1268	unsigned int alg_base_words, packed_patch_pos_words;
1269	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1270	unsigned int reg_addr;
1271	struct firmware *fw;
1272
1273	static_assert(sizeof(readback) == sizeof(packed_payload));
1274	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1275
1276	get_random_bytes(packed_payload, sizeof(packed_payload));
1277	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1278
1279	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1280							bin_test_mock_algs[param->alg_idx].id,
1281							param->mem_type);
1282	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1283
1284	/* Round packed start word up to a packed boundary and move to the next boundary */
1285	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1286
1287	/* Patch the leading unpacked words */
1288	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1289				  bin_test_mock_algs[param->alg_idx].id,
1290				  bin_test_mock_algs[param->alg_idx].ver,
1291				  unpacked_mem_type,
1292				  ((packed_patch_pos_words - 2) - alg_base_words) * 4,
1293				  unpacked_payload, sizeof(unpacked_payload));
1294	/* ... then the packed block */
1295	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1296	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1297				  bin_test_mock_algs[param->alg_idx].id,
1298				  bin_test_mock_algs[param->alg_idx].ver,
1299				  param->mem_type,
1300				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1301				  &packed_payload, sizeof(packed_payload));
1302
1303	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1304	KUNIT_ASSERT_EQ(test,
1305			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1306					fw, "mock_bin", "misc"),
1307			0);
1308
1309	/* Content of packed registers should match packed_payload */
1310	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1311		   (patch_pos_in_packed_regs * 4);
1312	memset(readback, 0, sizeof(readback));
1313	KUNIT_EXPECT_EQ(test,
1314			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1315			0);
1316	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1317
1318	/* Drop expected writes from the cache */
1319	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1320
1321	/* Content of unpacked registers should match unpacked_payload */
1322	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1323		   (packed_patch_pos_words - 2) * 4;
1324	memset(readback, 0, sizeof(readback));
1325	KUNIT_EXPECT_EQ(test,
1326			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1327					sizeof(unpacked_payload)),
1328			0);
1329	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1330
1331	/* Drop expected writes from the cache */
1332	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1333
1334	/* Drop expected writes and the cache should then be clean */
1335	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1336	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1337}
1338
1339/*
1340 * Patch data that starts three words before a packed boundary using three
1341 * unpacked words followed by one packed block.
1342 */
1343static void bin_patch_3_single_leading_1_packed(struct kunit *test)
1344{
1345	struct cs_dsp_test *priv = test->priv;
1346	const struct bin_test_param *param = test->param_value;
1347	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1348	u32 packed_payload[3], unpacked_payload[3], readback[3];
1349	unsigned int alg_base_words, packed_patch_pos_words;
1350	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1351	unsigned int reg_addr;
1352	struct firmware *fw;
1353
1354	static_assert(sizeof(readback) == sizeof(packed_payload));
1355	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1356
1357	get_random_bytes(packed_payload, sizeof(packed_payload));
1358	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1359
1360	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1361							bin_test_mock_algs[param->alg_idx].id,
1362							param->mem_type);
1363	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1364
1365	/* Round packed start word up to a packed boundary and move to the next boundary */
1366	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1367
1368	/* Patch the leading unpacked words */
1369	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1370				  bin_test_mock_algs[param->alg_idx].id,
1371				  bin_test_mock_algs[param->alg_idx].ver,
1372				  unpacked_mem_type,
1373				  ((packed_patch_pos_words - 3) - alg_base_words) * 4,
1374				  &unpacked_payload[0], sizeof(unpacked_payload[0]));
1375	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1376				  bin_test_mock_algs[param->alg_idx].id,
1377				  bin_test_mock_algs[param->alg_idx].ver,
1378				  unpacked_mem_type,
1379				  ((packed_patch_pos_words - 2) - alg_base_words) * 4,
1380				  &unpacked_payload[1], sizeof(unpacked_payload[1]));
1381	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1382				  bin_test_mock_algs[param->alg_idx].id,
1383				  bin_test_mock_algs[param->alg_idx].ver,
1384				  unpacked_mem_type,
1385				  ((packed_patch_pos_words - 1) - alg_base_words) * 4,
1386				  &unpacked_payload[2], sizeof(unpacked_payload[2]));
1387	/* ... then the packed block */
1388	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1389	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1390				  bin_test_mock_algs[param->alg_idx].id,
1391				  bin_test_mock_algs[param->alg_idx].ver,
1392				  param->mem_type,
1393				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1394				  &packed_payload, sizeof(packed_payload));
1395
1396	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1397	KUNIT_ASSERT_EQ(test,
1398			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1399					fw, "mock_bin", "misc"),
1400			0);
1401
1402	/* Content of packed registers should match packed_payload */
1403	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1404		   (patch_pos_in_packed_regs * 4);
1405	memset(readback, 0, sizeof(readback));
1406	KUNIT_EXPECT_EQ(test,
1407			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1408			0);
1409	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1410
1411	/* Drop expected writes from the cache */
1412	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1413
1414	/* Content of unpacked registers should match unpacked_payload */
1415	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1416		   (packed_patch_pos_words - 3) * 4;
1417	memset(readback, 0, sizeof(readback));
1418	KUNIT_EXPECT_EQ(test,
1419			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1420					sizeof(unpacked_payload)),
1421			0);
1422	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1423
1424	/* Drop expected writes from the cache */
1425	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1426
1427	/* Drop expected writes and the cache should then be clean */
1428	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1429	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1430}
1431
1432/*
1433 * Patch data that starts three words before a packed boundary using one
1434 * block of three unpacked words followed by one packed block.
1435 */
1436static void bin_patch_3_leading_1_packed(struct kunit *test)
1437{
1438	struct cs_dsp_test *priv = test->priv;
1439	const struct bin_test_param *param = test->param_value;
1440	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1441	u32 packed_payload[3], unpacked_payload[3], readback[3];
1442	unsigned int alg_base_words, packed_patch_pos_words;
1443	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1444	unsigned int reg_addr;
1445	struct firmware *fw;
1446
1447	static_assert(sizeof(readback) == sizeof(packed_payload));
1448	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1449
1450	get_random_bytes(packed_payload, sizeof(packed_payload));
1451	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1452
1453	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1454							bin_test_mock_algs[param->alg_idx].id,
1455							param->mem_type);
1456	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1457
1458	/* Round packed start word up to a packed boundary and move to the next boundary */
1459	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1460
1461	/* Patch the leading unpacked words */
1462	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1463				  bin_test_mock_algs[param->alg_idx].id,
1464				  bin_test_mock_algs[param->alg_idx].ver,
1465				  unpacked_mem_type,
1466				  ((packed_patch_pos_words - 3) - alg_base_words) * 4,
1467				  unpacked_payload, sizeof(unpacked_payload));
1468	/* ... then the packed block */
1469	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1470	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1471				  bin_test_mock_algs[param->alg_idx].id,
1472				  bin_test_mock_algs[param->alg_idx].ver,
1473				  param->mem_type,
1474				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1475				  &packed_payload, sizeof(packed_payload));
1476
1477	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1478	KUNIT_ASSERT_EQ(test,
1479			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1480					fw, "mock_bin", "misc"),
1481			0);
1482
1483	/* Content of packed registers should match packed_payload */
1484	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1485		   (patch_pos_in_packed_regs * 4);
1486	memset(readback, 0, sizeof(readback));
1487	KUNIT_EXPECT_EQ(test,
1488			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1489			0);
1490	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1491
1492	/* Drop expected writes from the cache */
1493	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1494
1495	/* Content of unpacked registers should match unpacked_payload */
1496	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1497		   (packed_patch_pos_words - 3) * 4;
1498	memset(readback, 0, sizeof(readback));
1499	KUNIT_EXPECT_EQ(test,
1500			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1501					sizeof(unpacked_payload)),
1502			0);
1503	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1504
1505	/* Drop expected writes from the cache */
1506	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1507
1508	/* Drop expected writes and the cache should then be clean */
1509	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1510	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1511}
1512
1513/* bin file with a multiple payloads that each patch one packed block. */
1514static void bin_patch_multi_onepacked(struct kunit *test)
1515{
1516	struct cs_dsp_test *priv = test->priv;
1517	const struct bin_test_param *param = test->param_value;
1518	u32 packed_payloads[8][3], readback[8][3];
1519	unsigned int alg_base_words, patch_pos_words;
1520	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1521	unsigned int payload_offset;
1522	unsigned int reg_addr;
1523	struct firmware *fw;
1524	int i;
1525
1526	static_assert(sizeof(readback) == sizeof(packed_payloads));
1527
1528	get_random_bytes(packed_payloads, sizeof(packed_payloads));
1529
1530	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1531							bin_test_mock_algs[param->alg_idx].id,
1532							param->mem_type);
1533	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1534
1535	/* Round patch start word up to a packed boundary */
1536	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1537
1538	/* Add one payload per packed block */
1539	for (i = 0; i < ARRAY_SIZE(packed_payloads); ++i) {
1540		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words + (i * 4));
1541		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1542		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1543					  bin_test_mock_algs[param->alg_idx].id,
1544					  bin_test_mock_algs[param->alg_idx].ver,
1545					  param->mem_type,
1546					  payload_offset,
1547					  &packed_payloads[i], sizeof(packed_payloads[i]));
1548	}
1549
1550	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1551	KUNIT_ASSERT_EQ(test,
1552			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1553					fw, "mock_bin", "misc"),
1554			0);
1555
1556	/* Content of packed registers should match packed_payloads */
1557	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1558	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1559		   (patch_pos_in_packed_regs * 4);
1560	memset(readback, 0, sizeof(readback));
1561	KUNIT_EXPECT_EQ(test,
1562			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1563			0);
1564	KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));
1565
1566	/* Drop expected writes and the cache should then be clean */
1567	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1568	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));
1569	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1570}
1571
1572/*
1573 * bin file with a multiple payloads that each patch one packed block.
1574 * The payloads are not in address order.
1575 */
1576static void bin_patch_multi_onepacked_unordered(struct kunit *test)
1577{
1578	struct cs_dsp_test *priv = test->priv;
1579	const struct bin_test_param *param = test->param_value;
1580	static const u8 payload_order[] = { 4, 3, 6, 1, 0, 7, 5, 2 };
1581	u32 packed_payloads[8][3], readback[8][3];
1582	unsigned int alg_base_words, patch_pos_words;
1583	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1584	unsigned int payload_offset;
1585	unsigned int reg_addr;
1586	struct firmware *fw;
1587	int i;
1588
1589	static_assert(ARRAY_SIZE(payload_order) == ARRAY_SIZE(packed_payloads));
1590	static_assert(sizeof(readback) == sizeof(packed_payloads));
1591
1592	get_random_bytes(packed_payloads, sizeof(packed_payloads));
1593
1594	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1595							bin_test_mock_algs[param->alg_idx].id,
1596							param->mem_type);
1597	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1598
1599	/* Round patch start word up to a packed boundary */
1600	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1601
1602	/* Add one payload per packed block */
1603	for (i = 0; i < ARRAY_SIZE(payload_order); ++i) {
1604		patch_pos_in_packed_regs =
1605			_num_words_to_num_packed_regs(patch_pos_words + (payload_order[i] * 4));
1606		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1607		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1608					  bin_test_mock_algs[param->alg_idx].id,
1609					  bin_test_mock_algs[param->alg_idx].ver,
1610					  param->mem_type,
1611					  payload_offset,
1612					  &packed_payloads[payload_order[i]],
1613					  sizeof(packed_payloads[0]));
1614	}
1615
1616	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1617	KUNIT_ASSERT_EQ(test,
1618			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1619					fw, "mock_bin", "misc"),
1620			0);
1621
1622	/* Content in registers should match the order of data in packed_payloads */
1623	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1624	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1625		   (patch_pos_in_packed_regs * 4);
1626	memset(readback, 0, sizeof(readback));
1627	KUNIT_EXPECT_EQ(test,
1628			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1629			0);
1630	KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));
1631
1632	/* Drop expected writes and the cache should then be clean */
1633	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1634	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));
1635	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1636}
1637
1638/*
1639 * bin file with a multiple payloads that each patch one packed block.
1640 * The payloads are not in address order. The patched memory is not contiguous.
1641 */
1642static void bin_patch_multi_onepacked_sparse_unordered(struct kunit *test)
1643{
1644	struct cs_dsp_test *priv = test->priv;
1645	const struct bin_test_param *param = test->param_value;
1646	static const u8 word_offsets[] = { 60, 24, 76, 4, 40, 52, 48, 36, 12 };
1647	u32 packed_payloads[9][3], readback[3];
1648	unsigned int alg_base_words, alg_base_in_packed_regs;
1649	unsigned int patch_pos_words, patch_pos_in_packed_regs, payload_offset;
1650	unsigned int reg_addr;
1651	struct firmware *fw;
1652	int i;
1653
1654	static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(packed_payloads));
1655	static_assert(sizeof(readback) == sizeof(packed_payloads[0]));
1656
1657	get_random_bytes(packed_payloads, sizeof(packed_payloads));
1658
1659	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1660							bin_test_mock_algs[param->alg_idx].id,
1661							param->mem_type);
1662	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1663
1664	/* Add one payload per packed block */
1665	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
1666		/* Round patch start word up to a packed boundary */
1667		patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);
1668		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1669		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1670		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1671					  bin_test_mock_algs[param->alg_idx].id,
1672					  bin_test_mock_algs[param->alg_idx].ver,
1673					  param->mem_type,
1674					  payload_offset,
1675					  &packed_payloads[i],
1676					  sizeof(packed_payloads[0]));
1677	}
1678
1679	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1680	KUNIT_ASSERT_EQ(test,
1681			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1682					fw, "mock_bin", "misc"),
1683			0);
1684
1685	/* Content of packed registers should match packed_payloads */
1686	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
1687		patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);
1688		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1689		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1690			   (patch_pos_in_packed_regs * 4);
1691		memset(readback, 0, sizeof(readback));
1692		KUNIT_EXPECT_EQ(test,
1693				regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1694						sizeof(readback)),
1695				0);
1696		KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads[i], sizeof(packed_payloads[i]));
1697
1698		/* Drop expected writes from the cache */
1699		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads[i]));
1700	}
1701
1702	/* Drop expected writes and the cache should then be clean */
1703	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1704	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1705}
1706
1707/*
1708 * bin file that patches a single packed block in each of the memory regions
1709 * of one algorithm.
1710 */
1711static void bin_patch_1_packed_multiple_mems(struct kunit *test)
1712{
1713	struct cs_dsp_test *priv = test->priv;
1714	const struct bin_test_param *param = test->param_value;
1715	u32 packed_xm_payload[3], packed_ym_payload[3], readback[3];
1716	unsigned int alg_xm_base_words, alg_ym_base_words;
1717	unsigned int xm_patch_pos_words, ym_patch_pos_words;
1718	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1719	unsigned int reg_addr;
1720	struct firmware *fw;
1721
1722	static_assert(sizeof(readback) == sizeof(packed_xm_payload));
1723	static_assert(sizeof(readback) == sizeof(packed_ym_payload));
1724
1725	get_random_bytes(packed_xm_payload, sizeof(packed_xm_payload));
1726	get_random_bytes(packed_ym_payload, sizeof(packed_ym_payload));
1727
1728	alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1729							bin_test_mock_algs[param->alg_idx].id,
1730							WMFW_HALO_XM_PACKED);
1731	alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1732							bin_test_mock_algs[param->alg_idx].id,
1733							WMFW_HALO_YM_PACKED);
1734
1735	/* Round patch start word up to a packed boundary */
1736	xm_patch_pos_words = round_up(alg_xm_base_words + param->offset_words, 4);
1737	ym_patch_pos_words = round_up(alg_ym_base_words + param->offset_words, 4);
1738
1739	/* Add XM and YM patches */
1740	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_xm_base_words);
1741	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);
1742	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1743				  bin_test_mock_algs[param->alg_idx].id,
1744				  bin_test_mock_algs[param->alg_idx].ver,
1745				  WMFW_HALO_XM_PACKED,
1746				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1747				  packed_xm_payload, sizeof(packed_xm_payload));
1748
1749	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_ym_base_words);
1750	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);
1751	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1752				  bin_test_mock_algs[param->alg_idx].id,
1753				  bin_test_mock_algs[param->alg_idx].ver,
1754				  WMFW_HALO_YM_PACKED,
1755				  (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1756				  packed_ym_payload, sizeof(packed_ym_payload));
1757
1758	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1759	KUNIT_ASSERT_EQ(test,
1760			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1761					fw, "mock_bin", "misc"),
1762			0);
1763
1764	/* Content of packed XM registers should match packed_xm_payload */
1765	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);
1766	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_XM_PACKED) +
1767		   (patch_pos_in_packed_regs * 4);
1768	memset(readback, 0, sizeof(readback));
1769	KUNIT_EXPECT_EQ(test,
1770			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1771			0);
1772	KUNIT_EXPECT_MEMEQ(test, readback, packed_xm_payload, sizeof(packed_xm_payload));
1773
1774	/* Drop expected writes from the cache */
1775	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_xm_payload));
1776
1777	/* Content of packed YM registers should match packed_ym_payload */
1778	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);
1779	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_YM_PACKED) +
1780		   (patch_pos_in_packed_regs * 4);
1781	memset(readback, 0, sizeof(readback));
1782	KUNIT_EXPECT_EQ(test,
1783			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1784			0);
1785	KUNIT_EXPECT_MEMEQ(test, readback, packed_ym_payload, sizeof(packed_ym_payload));
1786
1787	/* Drop expected writes from the cache */
1788	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_ym_payload));
1789
1790	/* Drop expected writes and the cache should then be clean */
1791	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1792	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1793}
1794
1795/*
1796 * bin file that patches a single packed block in multiple algorithms.
1797 */
1798static void bin_patch_1_packed_multiple_algs(struct kunit *test)
1799{
1800	struct cs_dsp_test *priv = test->priv;
1801	const struct bin_test_param *param = test->param_value;
1802	u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];
1803	u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];
1804	unsigned int alg_base_words, patch_pos_words;
1805	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1806	unsigned int reg_addr, payload_offset;
1807	struct firmware *fw;
1808	int i;
1809
1810	static_assert(sizeof(readback) == sizeof(packed_payload));
1811
1812	get_random_bytes(packed_payload, sizeof(packed_payload));
1813
1814	/* For each algorithm patch one DSP word to a value from packed_payload */
1815	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
1816		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1817								bin_test_mock_algs[i].id,
1818								param->mem_type);
1819		alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1820
1821		/* Round patch start word up to a packed boundary */
1822		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1823		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1824
1825		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1826		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1827					  bin_test_mock_algs[i].id,
1828					  bin_test_mock_algs[i].ver,
1829					  param->mem_type,
1830					  payload_offset,
1831					  packed_payload[i], sizeof(packed_payload[i]));
1832	}
1833
1834	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1835	KUNIT_ASSERT_EQ(test,
1836			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1837					fw, "mock_bin", "misc"),
1838			0);
1839
1840	memset(readback, 0, sizeof(readback));
1841
1842	/*
1843	 * Readback the registers that should have been written. Place
1844	 * the values into the expected location in readback[] so that
1845	 * the content of readback[] should match packed_payload[]
1846	 */
1847	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
1848		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1849								bin_test_mock_algs[i].id,
1850								param->mem_type);
1851		alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1852
1853		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1854		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1855
1856		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1857			   (patch_pos_in_packed_regs * 4);
1858		KUNIT_EXPECT_EQ(test,
1859				regmap_raw_read(priv->dsp->regmap, reg_addr,
1860						readback[i], sizeof(readback[i])),
1861				0);
1862
1863		/* Drop expected writes from the cache */
1864		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));
1865	}
1866
1867	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
1868
1869	/* Drop expected writes and the cache should then be clean */
1870	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1871	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1872}
1873
1874/*
1875 * bin file that patches a single packed block in multiple algorithms.
1876 * The algorithms are not patched in the same order they appear in the XM header.
1877 */
1878static void bin_patch_1_packed_multiple_algs_unordered(struct kunit *test)
1879{
1880	struct cs_dsp_test *priv = test->priv;
1881	const struct bin_test_param *param = test->param_value;
1882	static const u8 alg_order[] = { 3, 0, 2, 1 };
1883	u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];
1884	u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];
1885	unsigned int alg_base_words, patch_pos_words;
1886	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1887	unsigned int reg_addr, payload_offset;
1888	struct firmware *fw;
1889	int i, alg_idx;
1890
1891	static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));
1892	static_assert(sizeof(readback) == sizeof(packed_payload));
1893
1894	get_random_bytes(packed_payload, sizeof(packed_payload));
1895
1896	/*
1897	 * For each algorithm index in alg_order[] patch one DSP word in
1898	 * that algorithm to a value from packed_payload.
1899	 */
1900	for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {
1901		alg_idx = alg_order[i];
1902		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1903								bin_test_mock_algs[alg_idx].id,
1904								param->mem_type);
1905		alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1906
1907		/* Round patch start word up to a packed boundary */
1908		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1909		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1910
1911		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1912		cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
1913					  bin_test_mock_algs[alg_idx].id,
1914					  bin_test_mock_algs[alg_idx].ver,
1915					  param->mem_type,
1916					  payload_offset,
1917					  packed_payload[i], sizeof(packed_payload[i]));
1918	}
1919
1920	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1921	KUNIT_ASSERT_EQ(test,
1922			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1923					fw, "mock_bin", "misc"),
1924			0);
1925
1926	memset(readback, 0, sizeof(readback));
1927
1928	/*
1929	 * Readback the registers that should have been written. Place
1930	 * the values into the expected location in readback[] so that
1931	 * the content of readback[] should match packed_payload[]
1932	 */
1933	for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {
1934		alg_idx = alg_order[i];
1935		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1936								bin_test_mock_algs[alg_idx].id,
1937								param->mem_type);
1938
1939		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1940		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1941
1942		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1943			   (patch_pos_in_packed_regs * 4);
1944		KUNIT_EXPECT_EQ(test,
1945				regmap_raw_read(priv->dsp->regmap, reg_addr,
1946						readback[i], sizeof(readback[i])),
1947				0);
1948
1949		/* Drop expected writes from the cache */
1950		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));
1951	}
1952
1953	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
1954
1955	/* Drop expected writes and the cache should then be clean */
1956	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1957	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1958}
1959
1960/*
1961 * bin file that contains a mix of packed and unpacked words.
1962 * payloads are in random offset order. Offsets that are on a packed boundary
1963 * are written as a packed block. Offsets that are not on a packed boundary
1964 * are written as a single unpacked word.
1965 */
1966static void bin_patch_mixed_packed_unpacked_random(struct kunit *test)
1967{
1968	struct cs_dsp_test *priv = test->priv;
1969	const struct bin_test_param *param = test->param_value;
1970	static const u8 offset_words[] = {
1971		58, 68, 50, 10, 44, 17, 74, 36,  8,  7, 49, 11, 78, 57, 65, 2,
1972		48, 38, 22, 70, 77, 21, 61, 56, 75, 34, 27,  3, 31, 20,	43, 63,
1973		 5, 30, 32, 25, 33, 79, 29,  0,	37, 60, 69, 52, 13, 12, 24, 26,
1974		 4, 51, 76, 72, 16,  6, 39, 62, 15, 41, 28, 73, 53, 40, 45, 54,
1975		14, 55, 46, 66, 64, 59, 23,  9, 67, 47, 19, 71, 35, 18, 42,  1,
1976	};
1977	struct {
1978		u32 packed[80][3];
1979		u32 unpacked[80];
1980	} *payload;
1981	u32 readback[3];
1982	unsigned int alg_base_words, patch_pos_words;
1983	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1984	unsigned int reg_addr, payload_offset;
1985	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1986	struct firmware *fw;
1987	int i;
1988
1989	payload = kunit_kmalloc(test, sizeof(*payload), GFP_KERNEL);
1990	KUNIT_ASSERT_NOT_NULL(test, payload);
1991
1992	get_random_bytes(payload->packed, sizeof(payload->packed));
1993	get_random_bytes(payload->unpacked, sizeof(payload->unpacked));
1994
1995	/* Create a patch entry for every offset in offset_words[] */
1996	for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {
1997		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1998								bin_test_mock_algs[0].id,
1999								param->mem_type);
2000		/*
2001		 * If the offset is on a packed boundary use a packed payload else
2002		 * use an unpacked word
2003		 */
2004		patch_pos_words = alg_base_words + offset_words[i];
2005		if ((patch_pos_words % 4) == 0) {
2006			alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
2007			patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
2008			payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
2009			cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
2010						  bin_test_mock_algs[0].id,
2011						  bin_test_mock_algs[0].ver,
2012						  param->mem_type,
2013						  payload_offset,
2014						  payload->packed[i],
2015						  sizeof(payload->packed[i]));
2016		} else {
2017			payload_offset = offset_words[i] * 4;
2018			cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
2019						  bin_test_mock_algs[0].id,
2020						  bin_test_mock_algs[0].ver,
2021						  unpacked_mem_type,
2022						  payload_offset,
2023						  &payload->unpacked[i],
2024						  sizeof(payload->unpacked[i]));
2025		}
2026	}
2027
2028	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
2029	KUNIT_ASSERT_EQ(test,
2030			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
2031					fw, "mock_bin", "misc"),
2032			0);
2033
2034	/*
2035	 * Readback the packed registers that should have been written.
2036	 * Place the values into the expected location in readback[] so
2037	 * that the content of readback[] should match payload->packed[]
2038	 */
2039	for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {
2040		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2041								bin_test_mock_algs[0].id,
2042								param->mem_type);
2043		patch_pos_words = alg_base_words + offset_words[i];
2044
2045		/* Skip if the offset is not on a packed boundary */
2046		if ((patch_pos_words % 4) != 0)
2047			continue;
2048
2049		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
2050
2051		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
2052			   (patch_pos_in_packed_regs * 4);
2053
2054		memset(readback, 0, sizeof(readback));
2055		KUNIT_EXPECT_EQ(test,
2056				regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
2057						sizeof(readback)),
2058				0);
2059		KUNIT_EXPECT_MEMEQ(test, readback, payload->packed[i], sizeof(payload->packed[i]));
2060
2061		/* Drop expected writes from the cache */
2062		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->packed[i]));
2063	}
2064
2065	/*
2066	 * Readback the unpacked registers that should have been written.
2067	 * Place the values into the expected location in readback[] so
2068	 * that the content of readback[] should match payload->unpacked[]
2069	 */
2070	for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {
2071		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2072								bin_test_mock_algs[0].id,
2073								unpacked_mem_type);
2074
2075		patch_pos_words = alg_base_words + offset_words[i];
2076
2077		/* Skip if the offset is on a packed boundary */
2078		if ((patch_pos_words % 4) == 0)
2079			continue;
2080
2081		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
2082			   ((patch_pos_words) * 4);
2083
2084		readback[0] = 0;
2085		KUNIT_EXPECT_EQ(test,
2086				regmap_raw_read(priv->dsp->regmap, reg_addr,
2087						&readback[0], sizeof(readback[0])),
2088				0);
2089		KUNIT_EXPECT_EQ(test, readback[0], payload->unpacked[i]);
2090
2091		/* Drop expected writes from the cache */
2092		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->unpacked[i]));
2093	}
2094
2095	/* Drop expected writes and the cache should then be clean */
2096	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2097	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2098}
2099
2100/* Bin file with name and multiple info blocks */
2101static void bin_patch_name_and_info(struct kunit *test)
2102{
2103	struct cs_dsp_test *priv = test->priv;
2104	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2105	u32 reg_val, payload_data;
2106	char *infobuf;
2107	unsigned int alg_base_words, reg_addr;
2108	struct firmware *fw;
2109
2110	get_random_bytes(&payload_data, sizeof(payload_data));
2111
2112	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2113							bin_test_mock_algs[0].id,
2114							WMFW_ADSP2_YM);
2115
2116	/* Add a name block and info block */
2117	cs_dsp_mock_bin_add_name(priv->local->bin_builder, "The name");
2118	cs_dsp_mock_bin_add_info(priv->local->bin_builder, "Some info");
2119
2120	/* Add a big block of info */
2121	infobuf = kunit_kzalloc(test, 512, GFP_KERNEL);
2122	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, infobuf);
2123
2124	for (; strlcat(infobuf, "Waffle{Blah}\n", 512) < 512; )
2125		;
2126
2127	cs_dsp_mock_bin_add_info(priv->local->bin_builder, infobuf);
2128
2129	/* Add a patch */
2130	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
2131				  bin_test_mock_algs[0].id,
2132				  bin_test_mock_algs[0].ver,
2133				  WMFW_ADSP2_YM,
2134				  0,
2135				  &payload_data, sizeof(payload_data));
2136
2137	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
2138	KUNIT_ASSERT_EQ(test,
2139			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
2140					fw, "mock_bin", "misc"),
2141			0);
2142
2143	/* Content of registers should match payload_data */
2144	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
2145	reg_addr += alg_base_words * reg_inc_per_word;
2146	reg_val = 0;
2147	KUNIT_EXPECT_EQ(test,
2148			regmap_raw_read(priv->dsp->regmap, reg_addr,
2149					&reg_val, sizeof(reg_val)),
2150			0);
2151	KUNIT_EXPECT_EQ(test, reg_val, payload_data);
2152}
2153
2154static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp)
2155{
2156	struct cs_dsp_test *priv;
2157	struct cs_dsp_mock_xm_header *xm_hdr;
2158	struct device *test_dev;
2159	int ret;
2160
2161	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2162	if (!priv)
2163		return -ENOMEM;
2164
2165	priv->local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2166	if (!priv->local)
2167		return -ENOMEM;
2168
2169	priv->test = test;
2170	priv->dsp = dsp;
2171	test->priv = priv;
2172
2173	/* Create dummy struct device */
2174	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2175	if (IS_ERR(test_dev))
2176		return PTR_ERR(test_dev);
2177
2178	dsp->dev = get_device(test_dev);
2179	if (!dsp->dev)
2180		return -ENODEV;
2181
2182	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2183	if (ret)
2184		return ret;
2185
2186	dev_set_drvdata(dsp->dev, priv);
2187
2188	/* Allocate regmap */
2189	ret = cs_dsp_mock_regmap_init(priv);
2190	if (ret)
2191		return ret;
2192
2193	/* Create an XM header */
2194	xm_hdr = cs_dsp_create_mock_xm_header(priv,
2195					      bin_test_mock_algs,
2196					      ARRAY_SIZE(bin_test_mock_algs));
2197	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_hdr);
2198	ret = cs_dsp_mock_xm_header_write_to_regmap(xm_hdr);
2199	KUNIT_ASSERT_EQ(test, ret, 0);
2200
2201	priv->local->bin_builder =
2202		cs_dsp_mock_bin_init(priv, 1,
2203				     cs_dsp_mock_xm_header_get_fw_version(xm_hdr));
2204	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->local->bin_builder);
2205
2206	/* We must provide a dummy wmfw to load */
2207	priv->local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, -1);
2208	priv->local->wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2209
2210	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2211	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2212
2213	switch (dsp->type) {
2214	case WMFW_ADSP2:
2215		ret = cs_dsp_adsp2_init(dsp);
2216		break;
2217	case WMFW_HALO:
2218		ret = cs_dsp_halo_init(dsp);
2219		break;
2220	default:
2221		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2222		return -EINVAL;
2223	}
2224
2225	if (ret)
2226		return ret;
2227
2228	/* Automatically call cs_dsp_remove() when test case ends */
2229	ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2230	if (ret)
2231		return ret;
2232
2233	/*
2234	 * The large number of test cases will cause an unusually large amount
2235	 * of dev_info() messages from cs_dsp, so suppress these.
2236	 */
2237	cs_dsp_suppress_info_messages = true;
2238
2239	return 0;
2240}
2241
2242static void cs_dsp_bin_test_exit(struct kunit *test)
2243{
2244	cs_dsp_suppress_info_messages = false;
2245}
2246
2247static int cs_dsp_bin_test_halo_init(struct kunit *test)
2248{
2249	struct cs_dsp *dsp;
2250
2251	/* Fill in cs_dsp and initialize */
2252	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2253	if (!dsp)
2254		return -ENOMEM;
2255
2256	dsp->num = 1;
2257	dsp->type = WMFW_HALO;
2258	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2259	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2260	dsp->base = cs_dsp_mock_halo_core_base;
2261	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2262
2263	return cs_dsp_bin_test_common_init(test, dsp);
2264}
2265
2266static int cs_dsp_bin_test_adsp2_32bit_init(struct kunit *test)
2267{
2268	struct cs_dsp *dsp;
2269
2270	/* Fill in cs_dsp and initialize */
2271	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2272	if (!dsp)
2273		return -ENOMEM;
2274
2275	dsp->num = 1;
2276	dsp->type = WMFW_ADSP2;
2277	dsp->rev = 1;
2278	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2279	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2280	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2281
2282	return cs_dsp_bin_test_common_init(test, dsp);
2283}
2284
2285static int cs_dsp_bin_test_adsp2_16bit_init(struct kunit *test)
2286{
2287	struct cs_dsp *dsp;
2288
2289	/* Fill in cs_dsp and initialize */
2290	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2291	if (!dsp)
2292		return -ENOMEM;
2293
2294	dsp->num = 1;
2295	dsp->type = WMFW_ADSP2;
2296	dsp->rev = 0;
2297	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2298	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2299	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2300
2301	return cs_dsp_bin_test_common_init(test, dsp);
2302}
2303
2304/* Parameterize on choice of XM or YM with a range of word offsets */
2305static const struct bin_test_param x_or_y_and_offset_param_cases[] = {
2306	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0 },
2307	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 1 },
2308	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 2 },
2309	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 3 },
2310	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 4 },
2311	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 23 },
2312	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 22 },
2313	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 21 },
2314	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 20 },
2315
2316	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0 },
2317	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 1 },
2318	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 2 },
2319	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 3 },
2320	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 4 },
2321	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 23 },
2322	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 22 },
2323	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 21 },
2324	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 20 },
2325};
2326
2327/* Parameterize on ZM with a range of word offsets */
2328static const struct bin_test_param z_and_offset_param_cases[] = {
2329	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 0 },
2330	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 1 },
2331	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 2 },
2332	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 3 },
2333	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 4 },
2334	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 23 },
2335	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 22 },
2336	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 21 },
2337	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 20 },
2338};
2339
2340/* Parameterize on choice of packed XM or YM with a range of word offsets */
2341static const struct bin_test_param packed_x_or_y_and_offset_param_cases[] = {
2342	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0 },
2343	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 4 },
2344	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 8 },
2345	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 12 },
2346
2347	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0 },
2348	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 4 },
2349	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 8 },
2350	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 12 },
2351};
2352
2353static void x_or_y_or_z_and_offset_param_desc(const struct bin_test_param *param,
2354					   char *desc)
2355{
2356	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s@%u",
2357		 cs_dsp_mem_region_name(param->mem_type),
2358		 param->offset_words);
2359}
2360
2361KUNIT_ARRAY_PARAM(x_or_y_and_offset,
2362		  x_or_y_and_offset_param_cases,
2363		  x_or_y_or_z_and_offset_param_desc);
2364
2365KUNIT_ARRAY_PARAM(z_and_offset,
2366		  z_and_offset_param_cases,
2367		  x_or_y_or_z_and_offset_param_desc);
2368
2369KUNIT_ARRAY_PARAM(packed_x_or_y_and_offset,
2370		  packed_x_or_y_and_offset_param_cases,
2371		  x_or_y_or_z_and_offset_param_desc);
2372
2373/* Parameterize on choice of packed XM or YM */
2374static const struct bin_test_param packed_x_or_y_param_cases[] = {
2375	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0 },
2376	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0 },
2377};
2378
2379static void x_or_y_or_z_param_desc(const struct bin_test_param *param,
2380					   char *desc)
2381{
2382	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", cs_dsp_mem_region_name(param->mem_type));
2383}
2384
2385KUNIT_ARRAY_PARAM(packed_x_or_y, packed_x_or_y_param_cases, x_or_y_or_z_param_desc);
2386
2387static const struct bin_test_param offset_param_cases[] = {
2388	{ .offset_words = 0 },
2389	{ .offset_words = 1 },
2390	{ .offset_words = 2 },
2391	{ .offset_words = 3 },
2392	{ .offset_words = 4 },
2393	{ .offset_words = 23 },
2394	{ .offset_words = 22 },
2395	{ .offset_words = 21 },
2396	{ .offset_words = 20 },
2397};
2398
2399static void offset_param_desc(const struct bin_test_param *param, char *desc)
2400{
2401	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "@%u", param->offset_words);
2402}
2403
2404KUNIT_ARRAY_PARAM(offset, offset_param_cases, offset_param_desc);
2405
2406static const struct bin_test_param alg_param_cases[] = {
2407	{ .alg_idx = 0 },
2408	{ .alg_idx = 1 },
2409	{ .alg_idx = 2 },
2410	{ .alg_idx = 3 },
2411};
2412
2413static void alg_param_desc(const struct bin_test_param *param, char *desc)
2414{
2415	WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));
2416
2417	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg[%u] (%#x)",
2418		 param->alg_idx, bin_test_mock_algs[param->alg_idx].id);
2419}
2420
2421KUNIT_ARRAY_PARAM(alg, alg_param_cases, alg_param_desc);
2422
2423static const struct bin_test_param x_or_y_and_alg_param_cases[] = {
2424	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 0 },
2425	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 1 },
2426	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 2 },
2427	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 3 },
2428
2429	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 0 },
2430	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 1 },
2431	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 2 },
2432	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 3 },
2433};
2434
2435static void x_or_y_or_z_and_alg_param_desc(const struct bin_test_param *param, char *desc)
2436{
2437	WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));
2438
2439	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s alg[%u] (%#x)",
2440		 cs_dsp_mem_region_name(param->mem_type),
2441		 param->alg_idx, bin_test_mock_algs[param->alg_idx].id);
2442}
2443
2444KUNIT_ARRAY_PARAM(x_or_y_and_alg, x_or_y_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);
2445
2446static const struct bin_test_param z_and_alg_param_cases[] = {
2447	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 0 },
2448	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 1 },
2449	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 2 },
2450	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 3 },
2451};
2452
2453KUNIT_ARRAY_PARAM(z_and_alg, z_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);
2454
2455static const struct bin_test_param packed_x_or_y_and_alg_param_cases[] = {
2456	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 0 },
2457	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 1 },
2458	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 2 },
2459	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 3 },
2460
2461	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 0 },
2462	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 1 },
2463	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 2 },
2464	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 3 },
2465};
2466
2467KUNIT_ARRAY_PARAM(packed_x_or_y_and_alg, packed_x_or_y_and_alg_param_cases,
2468		  x_or_y_or_z_and_alg_param_desc);
2469
2470static struct kunit_case cs_dsp_bin_test_cases_halo[] = {
2471	/* Unpacked memory */
2472	KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),
2473	KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),
2474	KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),
2475	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),
2476	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),
2477	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),
2478	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),
2479	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),
2480	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),
2481
2482	/* Packed memory tests */
2483	KUNIT_CASE_PARAM(bin_patch_1_packed,
2484			 packed_x_or_y_and_offset_gen_params),
2485	KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,
2486			 packed_x_or_y_and_offset_gen_params),
2487	KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,
2488			 packed_x_or_y_and_offset_gen_params),
2489	KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,
2490			 packed_x_or_y_and_offset_gen_params),
2491	KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,
2492			 packed_x_or_y_and_offset_gen_params),
2493	KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,
2494			 packed_x_or_y_and_offset_gen_params),
2495	KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,
2496			 packed_x_or_y_and_offset_gen_params),
2497	KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,
2498			 packed_x_or_y_and_offset_gen_params),
2499	KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,
2500			 packed_x_or_y_and_offset_gen_params),
2501	KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,
2502			 packed_x_or_y_and_offset_gen_params),
2503	KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,
2504			 packed_x_or_y_and_offset_gen_params),
2505	KUNIT_CASE_PARAM(bin_patch_multi_onepacked,
2506			 packed_x_or_y_and_offset_gen_params),
2507	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,
2508			 packed_x_or_y_and_offset_gen_params),
2509	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, offset_gen_params),
2510	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_gen_params),
2511	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,
2512			 packed_x_or_y_and_alg_gen_params),
2513	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,
2514			 packed_x_or_y_and_offset_gen_params),
2515	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,
2516			 packed_x_or_y_and_offset_gen_params),
2517	KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,
2518			 packed_x_or_y_gen_params),
2519
2520	KUNIT_CASE(bin_patch_name_and_info),
2521
2522	{ } /* terminator */
2523};
2524
2525static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {
2526	/* XM and YM */
2527	KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),
2528	KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),
2529	KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),
2530	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),
2531	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),
2532	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),
2533	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),
2534
2535	/* ZM */
2536	KUNIT_CASE_PARAM(bin_patch_one_word, z_and_offset_gen_params),
2537	KUNIT_CASE_PARAM(bin_patch_one_multiword, z_and_offset_gen_params),
2538	KUNIT_CASE_PARAM(bin_patch_multi_oneword, z_and_offset_gen_params),
2539	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, z_and_offset_gen_params),
2540	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, z_and_alg_gen_params),
2541	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, z_and_offset_gen_params),
2542	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, z_and_offset_gen_params),
2543
2544	/* Other */
2545	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),
2546	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),
2547
2548	KUNIT_CASE(bin_patch_name_and_info),
2549
2550	{ } /* terminator */
2551};
2552
2553static struct kunit_suite cs_dsp_bin_test_halo = {
2554	.name = "cs_dsp_bin_halo",
2555	.init = cs_dsp_bin_test_halo_init,
2556	.exit = cs_dsp_bin_test_exit,
2557	.test_cases = cs_dsp_bin_test_cases_halo,
2558};
2559
2560static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {
2561	.name = "cs_dsp_bin_adsp2_32bit",
2562	.init = cs_dsp_bin_test_adsp2_32bit_init,
2563	.exit = cs_dsp_bin_test_exit,
2564	.test_cases = cs_dsp_bin_test_cases_adsp2,
2565};
2566
2567static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {
2568	.name = "cs_dsp_bin_adsp2_16bit",
2569	.init = cs_dsp_bin_test_adsp2_16bit_init,
2570	.exit = cs_dsp_bin_test_exit,
2571	.test_cases = cs_dsp_bin_test_cases_adsp2,
2572};
2573
2574kunit_test_suites(&cs_dsp_bin_test_halo,
2575		  &cs_dsp_bin_test_adsp2_32bit,
2576		  &cs_dsp_bin_test_adsp2_16bit);
~/ Read-only file preview.