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