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