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