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 
9 #include <kunit/device.h>
10 #include <kunit/resource.h>
11 #include <kunit/test.h>
12 #include <linux/build_bug.h>
13 #include <linux/firmware/cirrus/cs_dsp.h>
14 #include <linux/firmware/cirrus/cs_dsp_test_utils.h>
15 #include <linux/firmware/cirrus/wmfw.h>
16 #include <linux/random.h>
17 #include <linux/regmap.h>
18 #include <linux/string.h>
19 #include <linux/vmalloc.h>
20 
21 /*
22  * Test method is:
23  *
24  * 1) Create a mock regmap in cache-only mode so that all writes will be cached.
25  * 2) Create dummy wmfw file.
26  * 3) Call cs_dsp_power_up() with the bin file.
27  * 4) Readback the cached value of registers that should have been written and
28  *    check they have the correct value.
29  * 5) All the registers that are expected to have been written are dropped from
30  *    the cache. This should leave the cache clean.
31  * 6) If the cache is still dirty there have been unexpected writes.
32  */
33 
34 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)
35 KUNIT_DEFINE_ACTION_WRAPPER(_vfree_wrapper, vfree, void *)
36 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)
37 
38 struct cs_dsp_test_local {
39 	struct cs_dsp_mock_xm_header *xm_header;
40 	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
41 	int wmfw_version;
42 };
43 
44 struct cs_dsp_wmfw_test_param {
45 	unsigned int num_blocks;
46 	int mem_type;
47 };
48 
49 static const struct cs_dsp_mock_alg_def cs_dsp_wmfw_test_mock_algs[] = {
50 	{
51 		.id = 0xfafa,
52 		.ver = 0x100000,
53 		.xm_size_words = 164,
54 		.ym_size_words = 164,
55 		.zm_size_words = 164,
56 	},
57 };
58 
59 /*
60  * wmfw that writes the XM header.
61  * cs_dsp always reads this back from unpacked XM.
62  */
wmfw_write_xm_header_unpacked(struct kunit * test)63 static void wmfw_write_xm_header_unpacked(struct kunit *test)
64 {
65 	struct cs_dsp_test *priv = test->priv;
66 	struct cs_dsp_test_local *local = priv->local;
67 	struct firmware *wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
68 	unsigned int reg_addr;
69 	u8 *readback;
70 
71 	/* XM header payload was added to wmfw by test case init function */
72 
73 	KUNIT_EXPECT_EQ(test,
74 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
75 			0);
76 
77 	/* Read raw so endianness and register width don't matter */
78 	readback = kunit_kzalloc(test, local->xm_header->blob_size_bytes, GFP_KERNEL);
79 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
80 
81 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM);
82 	KUNIT_EXPECT_EQ(test,
83 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
84 					local->xm_header->blob_size_bytes),
85 			0);
86 	KUNIT_EXPECT_MEMEQ(test, readback, local->xm_header->blob_data,
87 			   local->xm_header->blob_size_bytes);
88 
89 	/* Drop expected writes and the cache should then be clean */
90 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
91 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
92 }
93 
94 /* Write one payload of length param->num_blocks */
wmfw_write_one_payload(struct kunit * test)95 static void wmfw_write_one_payload(struct kunit *test)
96 {
97 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
98 	struct cs_dsp_test *priv = test->priv;
99 	struct cs_dsp_test_local *local = priv->local;
100 	struct firmware *wmfw;
101 	unsigned int reg_addr;
102 	u8 *payload_data, *readback;
103 	unsigned int mem_offset_dsp_words = 0;
104 	unsigned int payload_size_bytes;
105 
106 	payload_size_bytes = param->num_blocks *
107 			     cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);
108 
109 	/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */
110 	do {
111 		payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);
112 	} while (payload_size_bytes % 4);
113 
114 	payload_data = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);
115 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
116 	get_random_bytes(payload_data, payload_size_bytes);
117 
118 	readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);
119 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
120 
121 	/* Tests on XM must be after the XM header */
122 	if (param->mem_type == WMFW_ADSP2_XM)
123 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);
124 
125 	/* Add a single payload */
126 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
127 					param->mem_type, mem_offset_dsp_words,
128 					payload_data, payload_size_bytes);
129 
130 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
131 
132 	KUNIT_EXPECT_EQ(test,
133 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
134 			0);
135 
136 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
137 	reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;
138 	KUNIT_EXPECT_EQ(test,
139 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),
140 			0);
141 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
142 
143 	/* Drop expected writes and the cache should then be clean */
144 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);
145 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
146 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
147 }
148 
149 /* Write several smallest possible payloads for the given memory type */
wmfw_write_multiple_oneblock_payloads(struct kunit * test)150 static void wmfw_write_multiple_oneblock_payloads(struct kunit *test)
151 {
152 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
153 	struct cs_dsp_test *priv = test->priv;
154 	struct cs_dsp_test_local *local = priv->local;
155 	struct firmware *wmfw;
156 	unsigned int reg_addr;
157 	u8 *payload_data, *readback;
158 	unsigned int mem_offset_dsp_words = 0;
159 	unsigned int payload_size_bytes, payload_size_dsp_words;
160 	const unsigned int num_payloads = param->num_blocks;
161 	int i;
162 
163 	/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */
164 	payload_size_dsp_words = 0;
165 	payload_size_bytes = 0;
166 	do {
167 		payload_size_dsp_words += cs_dsp_mock_reg_block_length_dsp_words(priv,
168 										 param->mem_type);
169 		payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);
170 	} while (payload_size_bytes % 4);
171 
172 	payload_data = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);
173 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
174 
175 	readback = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);
176 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
177 
178 	get_random_bytes(payload_data, num_payloads * payload_size_bytes);
179 
180 	/* Tests on XM must be after the XM header */
181 	if (param->mem_type == WMFW_ADSP2_XM)
182 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / payload_size_bytes;
183 
184 	/* Add multiple payloads of one block each */
185 	for (i = 0; i < num_payloads; ++i) {
186 		cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
187 						param->mem_type,
188 						mem_offset_dsp_words + (i * payload_size_dsp_words),
189 						&payload_data[i * payload_size_bytes],
190 						payload_size_bytes);
191 	}
192 
193 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
194 
195 	KUNIT_EXPECT_EQ(test,
196 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
197 			0);
198 
199 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
200 	reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;
201 	KUNIT_EXPECT_EQ(test,
202 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
203 					num_payloads * payload_size_bytes),
204 			0);
205 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, num_payloads * payload_size_bytes);
206 
207 	/* Drop expected writes and the cache should then be clean */
208 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, num_payloads * payload_size_bytes);
209 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
210 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
211 }
212 
213 /*
214  * Write several smallest possible payloads of the given memory type
215  * in reverse address order
216  */
wmfw_write_multiple_oneblock_payloads_reverse(struct kunit * test)217 static void wmfw_write_multiple_oneblock_payloads_reverse(struct kunit *test)
218 {
219 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
220 	struct cs_dsp_test *priv = test->priv;
221 	struct cs_dsp_test_local *local = priv->local;
222 	struct firmware *wmfw;
223 	unsigned int reg_addr;
224 	u8 *payload_data, *readback;
225 	unsigned int mem_offset_dsp_words = 0;
226 	unsigned int payload_size_bytes, payload_size_dsp_words;
227 	const unsigned int num_payloads = param->num_blocks;
228 	int i;
229 
230 	/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */
231 	payload_size_dsp_words = 0;
232 	payload_size_bytes = 0;
233 	do {
234 		payload_size_dsp_words += cs_dsp_mock_reg_block_length_dsp_words(priv,
235 										 param->mem_type);
236 		payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);
237 	} while (payload_size_bytes % 4);
238 
239 	payload_data = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);
240 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
241 
242 	readback = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);
243 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
244 
245 	get_random_bytes(payload_data, num_payloads * payload_size_bytes);
246 
247 	/* Tests on XM must be after the XM header */
248 	if (param->mem_type == WMFW_ADSP2_XM)
249 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / payload_size_bytes;
250 
251 	/* Add multiple payloads of one block each */
252 	for (i = num_payloads - 1; i >= 0; --i) {
253 		cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
254 						param->mem_type,
255 						mem_offset_dsp_words + (i * payload_size_dsp_words),
256 						&payload_data[i * payload_size_bytes],
257 						payload_size_bytes);
258 	}
259 
260 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
261 
262 	KUNIT_EXPECT_EQ(test,
263 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
264 			0);
265 
266 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
267 	reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;
268 	KUNIT_EXPECT_EQ(test,
269 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
270 					num_payloads * payload_size_bytes),
271 			0);
272 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, num_payloads * payload_size_bytes);
273 
274 	/* Drop expected writes and the cache should then be clean */
275 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, num_payloads * payload_size_bytes);
276 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
277 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
278 }
279 
280 /*
281  * Write multiple payloads of length param->num_blocks.
282  * The payloads are not in address order and collectively do not patch
283  * a contiguous block of memory.
284  */
wmfw_write_multiple_payloads_sparse_unordered(struct kunit * test)285 static void wmfw_write_multiple_payloads_sparse_unordered(struct kunit *test)
286 {
287 	static const unsigned int random_offsets[] = {
288 		11, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,
289 		54, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,
290 		29, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22
291 	};
292 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
293 	struct cs_dsp_test *priv = test->priv;
294 	struct cs_dsp_test_local *local = priv->local;
295 	struct firmware *wmfw;
296 	unsigned int reg_addr;
297 	u8 *payload_data, *readback;
298 	unsigned int mem_offset_dsp_words = 0;
299 	unsigned int payload_size_bytes, payload_size_dsp_words;
300 	const int num_payloads = ARRAY_SIZE(random_offsets);
301 	int i;
302 
303 	payload_size_bytes = param->num_blocks *
304 			     cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);
305 	payload_size_dsp_words = param->num_blocks *
306 				 cs_dsp_mock_reg_block_length_dsp_words(priv, param->mem_type);
307 
308 	/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */
309 	do {
310 		payload_size_dsp_words += cs_dsp_mock_reg_block_length_dsp_words(priv,
311 										 param->mem_type);
312 		payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);
313 	} while (payload_size_bytes % 4);
314 
315 	payload_data = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);
316 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
317 	get_random_bytes(payload_data, payload_size_bytes);
318 
319 	readback = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);
320 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
321 
322 	/* Tests on XM must be after the XM header */
323 	if (param->mem_type == WMFW_ADSP2_XM)
324 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / payload_size_bytes;
325 
326 	/* Add multiple payloads of one block each at "random" locations */
327 	for (i = 0; i < num_payloads; ++i) {
328 		unsigned int offset = random_offsets[i] * payload_size_dsp_words;
329 
330 		cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
331 						param->mem_type,
332 						mem_offset_dsp_words + offset,
333 						&payload_data[i * payload_size_bytes],
334 						payload_size_bytes);
335 	}
336 
337 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
338 
339 	KUNIT_EXPECT_EQ(test,
340 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
341 			0);
342 
343 	for (i = 0; i < num_payloads; ++i) {
344 		unsigned int offset_num_regs = (random_offsets[i] * payload_size_bytes) /
345 						regmap_get_val_bytes(priv->dsp->regmap);
346 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
347 		reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
348 		reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;
349 		KUNIT_EXPECT_EQ(test,
350 				regmap_raw_read(priv->dsp->regmap, reg_addr,
351 						&readback[i * payload_size_bytes],
352 						payload_size_bytes),
353 				0);
354 
355 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);
356 	}
357 
358 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
359 
360 	/* Drop expected writes and the cache should then be clean */
361 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
362 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
363 }
364 
365 /* Write the whole of PM in a single unpacked payload */
wmfw_write_all_unpacked_pm(struct kunit * test)366 static void wmfw_write_all_unpacked_pm(struct kunit *test)
367 {
368 	struct cs_dsp_test *priv = test->priv;
369 	struct cs_dsp_test_local *local = priv->local;
370 	struct firmware *wmfw;
371 	unsigned int reg_addr;
372 	u8 *payload_data, *readback;
373 	unsigned int payload_size_bytes;
374 
375 	payload_size_bytes = cs_dsp_mock_size_of_region(priv->dsp, WMFW_ADSP2_PM);
376 	payload_data = vmalloc(payload_size_bytes);
377 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
378 	kunit_add_action_or_reset(priv->test, _vfree_wrapper, payload_data);
379 
380 	readback = vmalloc(payload_size_bytes);
381 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
382 	kunit_add_action_or_reset(priv->test, _vfree_wrapper, readback);
383 	memset(readback, 0, payload_size_bytes);
384 
385 	/* Add a single PM payload */
386 	get_random_bytes(payload_data, payload_size_bytes);
387 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
388 					WMFW_ADSP2_PM, 0,
389 					payload_data, payload_size_bytes);
390 
391 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
392 
393 	KUNIT_EXPECT_EQ(test,
394 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
395 			0);
396 
397 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_PM);
398 	KUNIT_EXPECT_EQ(test,
399 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),
400 			0);
401 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
402 
403 	/* Drop expected writes and the cache should then be clean */
404 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);
405 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
406 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
407 }
408 
409 /* Write the whole of PM in a single packed payload */
wmfw_write_all_packed_pm(struct kunit * test)410 static void wmfw_write_all_packed_pm(struct kunit *test)
411 {
412 	struct cs_dsp_test *priv = test->priv;
413 	struct cs_dsp_test_local *local = priv->local;
414 	struct firmware *wmfw;
415 	unsigned int reg_addr;
416 	u8 *payload_data, *readback;
417 	unsigned int payload_size_bytes;
418 
419 	payload_size_bytes = cs_dsp_mock_size_of_region(priv->dsp, WMFW_HALO_PM_PACKED);
420 	payload_data = vmalloc(payload_size_bytes);
421 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
422 	kunit_add_action_or_reset(priv->test, _vfree_wrapper, payload_data);
423 
424 	readback = vmalloc(payload_size_bytes);
425 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
426 	kunit_add_action_or_reset(priv->test, _vfree_wrapper, readback);
427 	memset(readback, 0, payload_size_bytes);
428 
429 	/* Add a single PM payload */
430 	get_random_bytes(payload_data, payload_size_bytes);
431 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
432 					WMFW_HALO_PM_PACKED, 0,
433 					payload_data, payload_size_bytes);
434 
435 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
436 
437 	KUNIT_EXPECT_EQ(test,
438 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
439 			0);
440 
441 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_PM_PACKED);
442 	KUNIT_EXPECT_EQ(test,
443 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),
444 			0);
445 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
446 
447 	/* Drop expected writes and the cache should then be clean */
448 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);
449 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
450 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
451 }
452 
453 /*
454  * Write a series of payloads to various unpacked memory regions.
455  * The payloads are of various lengths and offsets, driven by the
456  * payload_defs table. The offset and length are both given as a
457  * number of minimum-sized register blocks to keep the maths simpler.
458  * (Where a minimum-sized register block is the smallest number of
459  * registers that contain a whole number of DSP words.)
460  */
wmfw_write_multiple_unpacked_mem(struct kunit * test)461 static void wmfw_write_multiple_unpacked_mem(struct kunit *test)
462 {
463 	static const struct {
464 		int mem_type;
465 		unsigned int offset_num_blocks;
466 		unsigned int num_blocks;
467 	} payload_defs[] = {
468 		{ WMFW_ADSP2_PM, 11, 60 },
469 		{ WMFW_ADSP2_ZM, 69, 8 },
470 		{ WMFW_ADSP2_YM, 32, 74 },
471 		{ WMFW_ADSP2_XM, 70, 38 },
472 		{ WMFW_ADSP2_PM, 84, 48 },
473 		{ WMFW_ADSP2_XM, 46, 18 },
474 		{ WMFW_ADSP2_PM, 0,  8 },
475 		{ WMFW_ADSP2_YM, 0, 30 },
476 		{ WMFW_ADSP2_PM, 160, 50 },
477 		{ WMFW_ADSP2_ZM, 21, 26 },
478 	};
479 	struct cs_dsp_test *priv = test->priv;
480 	struct cs_dsp_test_local *local = priv->local;
481 	struct firmware *wmfw;
482 	unsigned int payload_size_bytes, offset_num_dsp_words;
483 	unsigned int reg_addr, offset_bytes, offset_num_regs;
484 	void **payload_data;
485 	void *readback;
486 	int i, ret;
487 
488 	payload_data = kunit_kcalloc(test, ARRAY_SIZE(payload_defs), sizeof(*payload_data),
489 				     GFP_KERNEL);
490 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
491 
492 	for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {
493 		payload_size_bytes = payload_defs[i].num_blocks *
494 				     cs_dsp_mock_reg_block_length_bytes(priv,
495 									payload_defs[i].mem_type);
496 
497 		payload_data[i] = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);
498 		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data[i]);
499 		get_random_bytes(payload_data[i], payload_size_bytes);
500 
501 		offset_num_dsp_words = payload_defs[i].offset_num_blocks *
502 				       cs_dsp_mock_reg_block_length_dsp_words(priv,
503 									 payload_defs[i].mem_type);
504 		cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
505 						payload_defs[i].mem_type,
506 						offset_num_dsp_words,
507 						payload_data[i],
508 						payload_size_bytes);
509 	}
510 
511 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
512 
513 	KUNIT_EXPECT_EQ(test,
514 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
515 			0);
516 
517 	for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {
518 		payload_size_bytes = payload_defs[i].num_blocks *
519 				     cs_dsp_mock_reg_block_length_bytes(priv,
520 									payload_defs[i].mem_type);
521 
522 		readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);
523 		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
524 
525 		offset_bytes = payload_defs[i].offset_num_blocks *
526 			       cs_dsp_mock_reg_block_length_bytes(priv, payload_defs[i].mem_type);
527 		offset_num_regs = offset_bytes / regmap_get_val_bytes(priv->dsp->regmap);
528 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, payload_defs[i].mem_type);
529 		reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
530 		ret = regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes);
531 		KUNIT_EXPECT_EQ_MSG(test, ret, 0, "%s @%u num:%u\n",
532 				    cs_dsp_mem_region_name(payload_defs[i].mem_type),
533 				    payload_defs[i].offset_num_blocks, payload_defs[i].num_blocks);
534 		KUNIT_EXPECT_MEMEQ_MSG(test, readback, payload_data[i], payload_size_bytes,
535 				       "%s @%u num:%u\n",
536 				       cs_dsp_mem_region_name(payload_defs[i].mem_type),
537 				       payload_defs[i].offset_num_blocks,
538 				       payload_defs[i].num_blocks);
539 
540 		kunit_kfree(test, readback);
541 
542 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);
543 	}
544 
545 	/* Drop expected writes and the cache should then be clean */
546 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
547 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
548 }
549 
550 /*
551  * Write a series of payloads to various packed and unpacked memory regions.
552  * The payloads are of various lengths and offsets, driven by the
553  * payload_defs table. The offset and length are both given as a
554  * number of minimum-sized register blocks to keep the maths simpler.
555  * (Where a minimum-sized register block is the smallest number of
556  * registers that contain a whole number of DSP words.)
557  */
wmfw_write_multiple_packed_unpacked_mem(struct kunit * test)558 static void wmfw_write_multiple_packed_unpacked_mem(struct kunit *test)
559 {
560 	static const struct {
561 		int mem_type;
562 		unsigned int offset_num_blocks;
563 		unsigned int num_blocks;
564 	} payload_defs[] = {
565 		{ WMFW_HALO_PM_PACKED,	11, 60 },
566 		{ WMFW_ADSP2_YM,	69, 8 },
567 		{ WMFW_HALO_YM_PACKED,	32, 74 },
568 		{ WMFW_HALO_XM_PACKED,	70, 38 },
569 		{ WMFW_HALO_PM_PACKED,	84, 48 },
570 		{ WMFW_HALO_XM_PACKED,	46, 18 },
571 		{ WMFW_HALO_PM_PACKED,	0,  8 },
572 		{ WMFW_HALO_YM_PACKED,	0, 30 },
573 		{ WMFW_HALO_PM_PACKED,	160, 50 },
574 		{ WMFW_ADSP2_XM,	21, 26 },
575 	};
576 	struct cs_dsp_test *priv = test->priv;
577 	struct cs_dsp_test_local *local = priv->local;
578 	struct firmware *wmfw;
579 	unsigned int payload_size_bytes, offset_num_dsp_words;
580 	unsigned int reg_addr, offset_bytes, offset_num_regs;
581 	void **payload_data;
582 	void *readback;
583 	int i, ret;
584 
585 	payload_data = kunit_kcalloc(test, ARRAY_SIZE(payload_defs), sizeof(*payload_data),
586 				     GFP_KERNEL);
587 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
588 
589 	for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {
590 		payload_size_bytes = payload_defs[i].num_blocks *
591 				     cs_dsp_mock_reg_block_length_bytes(priv,
592 									payload_defs[i].mem_type);
593 
594 		payload_data[i] = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);
595 		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data[i]);
596 		get_random_bytes(payload_data[i], payload_size_bytes);
597 
598 		offset_num_dsp_words = payload_defs[i].offset_num_blocks *
599 				       cs_dsp_mock_reg_block_length_dsp_words(priv,
600 									 payload_defs[i].mem_type);
601 		cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
602 						payload_defs[i].mem_type,
603 						offset_num_dsp_words,
604 						payload_data[i],
605 						payload_size_bytes);
606 	}
607 
608 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
609 
610 	KUNIT_EXPECT_EQ(test,
611 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
612 			0);
613 
614 	for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {
615 		payload_size_bytes = payload_defs[i].num_blocks *
616 				     cs_dsp_mock_reg_block_length_bytes(priv,
617 									payload_defs[i].mem_type);
618 
619 		readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);
620 		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
621 
622 		offset_bytes = payload_defs[i].offset_num_blocks *
623 			       cs_dsp_mock_reg_block_length_bytes(priv, payload_defs[i].mem_type);
624 		offset_num_regs = offset_bytes / regmap_get_val_bytes(priv->dsp->regmap);
625 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, payload_defs[i].mem_type);
626 		reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
627 		ret = regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes);
628 		KUNIT_EXPECT_EQ_MSG(test, ret, 0, "%s @%u num:%u\n",
629 				    cs_dsp_mem_region_name(payload_defs[i].mem_type),
630 				    payload_defs[i].offset_num_blocks,
631 				    payload_defs[i].num_blocks);
632 		KUNIT_EXPECT_MEMEQ_MSG(test, readback, payload_data[i], payload_size_bytes,
633 				       "%s @%u num:%u\n",
634 				       cs_dsp_mem_region_name(payload_defs[i].mem_type),
635 				       payload_defs[i].offset_num_blocks,
636 				       payload_defs[i].num_blocks);
637 
638 		kunit_kfree(test, readback);
639 
640 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);
641 	}
642 
643 	/* Drop expected writes and the cache should then be clean */
644 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
645 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
646 }
647 
648 /*
649  * Write XM/YM data that is one word longer than a packed block multiple,
650  * using one packed payload followed by one unpacked word.
651  */
wmfw_write_packed_1_unpacked_trailing(struct kunit * test)652 static void wmfw_write_packed_1_unpacked_trailing(struct kunit *test)
653 {
654 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
655 	struct cs_dsp_test *priv = test->priv;
656 	struct cs_dsp_test_local *local = priv->local;
657 	int packed_mem_type = param->mem_type;
658 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
659 	unsigned int dsp_words_per_packed_block =
660 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
661 	unsigned int dsp_words_per_unpacked_block =
662 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
663 	unsigned int mem_offset_dsp_words = 0;
664 	struct firmware *wmfw;
665 	unsigned int reg_addr;
666 	void *packed_payload_data, *readback;
667 	u32 unpacked_payload_data[1];
668 	unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;
669 	unsigned int offset_num_regs;
670 
671 	packed_payload_size_bytes = param->num_blocks *
672 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
673 	packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;
674 
675 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
676 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
677 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
678 
679 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
680 
681 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
682 
683 	/* Tests on XM must be after the XM header */
684 	if (unpacked_mem_type == WMFW_ADSP2_XM) {
685 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);
686 
687 		/* Round up to multiple of packed block length */
688 		mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);
689 	}
690 
691 	/* Add a single packed payload */
692 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
693 					packed_mem_type, mem_offset_dsp_words,
694 					packed_payload_data, packed_payload_size_bytes);
695 	/*
696 	 * Add payload of one unpacked word to DSP memory right after
697 	 * the packed payload words.
698 	 */
699 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
700 					unpacked_mem_type,
701 					mem_offset_dsp_words + packed_payload_size_dsp_words,
702 					unpacked_payload_data, sizeof(unpacked_payload_data));
703 
704 	/* Download the wmfw */
705 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
706 	KUNIT_EXPECT_EQ(test,
707 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
708 			0);
709 
710 	/*
711 	 * Check that the packed payload was written correctly and drop
712 	 * it from the regmap cache.
713 	 */
714 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *
715 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
716 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
717 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
718 	KUNIT_EXPECT_EQ(test,
719 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
720 					packed_payload_size_bytes),
721 			0);
722 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
723 
724 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
725 
726 	/*
727 	 * Check that the unpacked word was written correctly and drop
728 	 * it from the regmap cache. The unpacked payload is offset within
729 	 * unpacked register space by the number of DSP words that were
730 	 * written in the packed payload.
731 	 */
732 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *
733 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
734 	offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *
735 			   cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
736 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
737 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
738 	KUNIT_EXPECT_EQ(test,
739 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
740 					sizeof(unpacked_payload_data)),
741 			0);
742 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
743 
744 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
745 
746 	/* Drop expected writes and the cache should then be clean */
747 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
748 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
749 }
750 
751 /*
752  * Write XM/YM data that is two words longer than a packed block multiple,
753  * using one packed payload followed by one payload of two unpacked words.
754  */
wmfw_write_packed_2_unpacked_trailing(struct kunit * test)755 static void wmfw_write_packed_2_unpacked_trailing(struct kunit *test)
756 {
757 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
758 	struct cs_dsp_test *priv = test->priv;
759 	struct cs_dsp_test_local *local = priv->local;
760 	int packed_mem_type = param->mem_type;
761 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
762 	unsigned int dsp_words_per_packed_block =
763 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
764 	unsigned int dsp_words_per_unpacked_block =
765 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
766 	unsigned int mem_offset_dsp_words = 0;
767 	struct firmware *wmfw;
768 	unsigned int reg_addr;
769 	void *packed_payload_data, *readback;
770 	u32 unpacked_payload_data[2];
771 	unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;
772 	unsigned int offset_num_regs;
773 
774 	packed_payload_size_bytes = param->num_blocks *
775 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
776 	packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;
777 
778 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
779 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
780 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
781 
782 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
783 
784 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
785 
786 	/* Tests on XM must be after the XM header */
787 	if (unpacked_mem_type == WMFW_ADSP2_XM) {
788 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);
789 
790 		/* Round up to multiple of packed block length */
791 		mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);
792 	}
793 
794 	/* Add a single packed payload */
795 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
796 					packed_mem_type, mem_offset_dsp_words,
797 					packed_payload_data, packed_payload_size_bytes);
798 	/*
799 	 * Add payload of two unpacked words to DSP memory right after
800 	 * the packed payload words.
801 	 */
802 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
803 					unpacked_mem_type,
804 					mem_offset_dsp_words + packed_payload_size_dsp_words,
805 					unpacked_payload_data, sizeof(unpacked_payload_data));
806 
807 	/* Download the wmfw */
808 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
809 	KUNIT_EXPECT_EQ(test,
810 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
811 			0);
812 
813 	/*
814 	 * Check that the packed payload was written correctly and drop
815 	 * it from the regmap cache.
816 	 */
817 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *
818 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
819 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
820 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
821 	KUNIT_EXPECT_EQ(test,
822 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
823 					packed_payload_size_bytes),
824 			0);
825 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
826 
827 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
828 
829 	/*
830 	 * Check that the unpacked words were written correctly and drop
831 	 * them from the regmap cache. The unpacked payload is offset
832 	 * within unpacked register space by the number of DSP words
833 	 * that were written in the packed payload.
834 	 */
835 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *
836 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
837 	offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *
838 			   cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
839 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
840 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
841 	KUNIT_EXPECT_EQ(test,
842 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
843 					sizeof(unpacked_payload_data)),
844 			0);
845 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
846 
847 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
848 
849 	/* Drop expected writes and the cache should then be clean */
850 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
851 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
852 }
853 
854 /*
855  * Write XM/YM data that is three words longer than a packed block multiple,
856  * using one packed payload followed by one payload of three unpacked words.
857  */
wmfw_write_packed_3_unpacked_trailing(struct kunit * test)858 static void wmfw_write_packed_3_unpacked_trailing(struct kunit *test)
859 {
860 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
861 	struct cs_dsp_test *priv = test->priv;
862 	struct cs_dsp_test_local *local = priv->local;
863 	int packed_mem_type = param->mem_type;
864 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
865 	unsigned int dsp_words_per_packed_block =
866 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
867 	unsigned int dsp_words_per_unpacked_block =
868 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
869 	unsigned int mem_offset_dsp_words = 0;
870 	struct firmware *wmfw;
871 	unsigned int reg_addr;
872 	void *packed_payload_data, *readback;
873 	u32 unpacked_payload_data[3];
874 	unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;
875 	unsigned int offset_num_regs;
876 
877 	packed_payload_size_bytes = param->num_blocks *
878 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
879 	packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;
880 
881 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
882 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
883 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
884 
885 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
886 
887 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
888 
889 	/* Tests on XM must be after the XM header */
890 	if (unpacked_mem_type == WMFW_ADSP2_XM) {
891 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);
892 
893 		/* Round up to multiple of packed block length */
894 		mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);
895 	}
896 
897 	/* Add a single packed payload */
898 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
899 					packed_mem_type, mem_offset_dsp_words,
900 					packed_payload_data, packed_payload_size_bytes);
901 	/*
902 	 * Add payload of three unpacked words to DSP memory right after
903 	 * the packed payload words.
904 	 */
905 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
906 					unpacked_mem_type,
907 					mem_offset_dsp_words + packed_payload_size_dsp_words,
908 					unpacked_payload_data, sizeof(unpacked_payload_data));
909 
910 	/* Download the wmfw */
911 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
912 	KUNIT_EXPECT_EQ(test,
913 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
914 			0);
915 
916 	/*
917 	 * Check that the packed payload was written correctly and drop
918 	 * it from the regmap cache.
919 	 */
920 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *
921 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
922 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
923 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
924 	KUNIT_EXPECT_EQ(test,
925 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
926 					packed_payload_size_bytes),
927 			0);
928 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
929 
930 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
931 
932 	/*
933 	 * Check that the unpacked words were written correctly and drop
934 	 * them from the regmap cache. The unpacked payload is offset
935 	 * within unpacked register space by the number of DSP words
936 	 * that were written in the packed payload.
937 	 */
938 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *
939 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
940 	offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *
941 			   cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
942 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
943 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
944 	KUNIT_EXPECT_EQ(test,
945 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
946 					sizeof(unpacked_payload_data)),
947 			0);
948 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
949 
950 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
951 
952 	/* Drop expected writes and the cache should then be clean */
953 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
954 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
955 }
956 
957 /*
958  * Write XM/YM data that is two words longer than a packed block multiple,
959  * using one packed payload followed by two payloads of one unpacked word each.
960  */
wmfw_write_packed_2_single_unpacked_trailing(struct kunit * test)961 static void wmfw_write_packed_2_single_unpacked_trailing(struct kunit *test)
962 {
963 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
964 	struct cs_dsp_test *priv = test->priv;
965 	struct cs_dsp_test_local *local = priv->local;
966 	int packed_mem_type = param->mem_type;
967 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
968 	unsigned int dsp_words_per_packed_block =
969 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
970 	unsigned int dsp_words_per_unpacked_block =
971 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
972 	unsigned int mem_offset_dsp_words = 0;
973 	struct firmware *wmfw;
974 	unsigned int reg_addr;
975 	void *packed_payload_data, *readback;
976 	u32 unpacked_payload_data[2];
977 	unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;
978 	unsigned int offset_num_regs;
979 
980 	packed_payload_size_bytes = param->num_blocks *
981 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
982 	packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;
983 
984 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
985 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
986 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
987 
988 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
989 
990 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
991 
992 	/* Tests on XM must be after the XM header */
993 	if (unpacked_mem_type == WMFW_ADSP2_XM) {
994 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);
995 
996 		/* Round up to multiple of packed block length */
997 		mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);
998 	}
999 
1000 	/* Add a single packed payload */
1001 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1002 					packed_mem_type, mem_offset_dsp_words,
1003 					packed_payload_data, packed_payload_size_bytes);
1004 	/*
1005 	 * Add two unpacked words to DSP memory right after the packed
1006 	 * payload words. Each unpacked word in its own payload.
1007 	 */
1008 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1009 					unpacked_mem_type,
1010 					mem_offset_dsp_words + packed_payload_size_dsp_words,
1011 					&unpacked_payload_data[0],
1012 					sizeof(unpacked_payload_data[0]));
1013 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1014 					unpacked_mem_type,
1015 					mem_offset_dsp_words + packed_payload_size_dsp_words + 1,
1016 					&unpacked_payload_data[1],
1017 					sizeof(unpacked_payload_data[1]));
1018 
1019 	/* Download the wmfw */
1020 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1021 	KUNIT_EXPECT_EQ(test,
1022 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1023 			0);
1024 
1025 	/*
1026 	 * Check that the packed payload was written correctly and drop
1027 	 * it from the regmap cache.
1028 	 */
1029 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *
1030 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1031 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1032 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1033 	KUNIT_EXPECT_EQ(test,
1034 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1035 					packed_payload_size_bytes),
1036 			0);
1037 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1038 
1039 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1040 
1041 	/*
1042 	 * Check that the unpacked words were written correctly and drop
1043 	 * them from the regmap cache. The unpacked words are offset
1044 	 * within unpacked register space by the number of DSP words
1045 	 * that were written in the packed payload.
1046 	 */
1047 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *
1048 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1049 	offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *
1050 			   cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1051 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1052 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1053 	KUNIT_EXPECT_EQ(test,
1054 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1055 					sizeof(unpacked_payload_data)),
1056 			0);
1057 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1058 
1059 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1060 
1061 	/* Drop expected writes and the cache should then be clean */
1062 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1063 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1064 }
1065 
1066 /*
1067  * Write XM/YM data that is three words longer than a packed block multiple,
1068  * using one packed payload followed by three payloads of one unpacked word each.
1069  */
wmfw_write_packed_3_single_unpacked_trailing(struct kunit * test)1070 static void wmfw_write_packed_3_single_unpacked_trailing(struct kunit *test)
1071 {
1072 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
1073 	struct cs_dsp_test *priv = test->priv;
1074 	struct cs_dsp_test_local *local = priv->local;
1075 	int packed_mem_type = param->mem_type;
1076 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1077 	unsigned int dsp_words_per_packed_block =
1078 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
1079 	unsigned int dsp_words_per_unpacked_block =
1080 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
1081 	unsigned int mem_offset_dsp_words = 0;
1082 	struct firmware *wmfw;
1083 	unsigned int reg_addr;
1084 	void *packed_payload_data, *readback;
1085 	u32 unpacked_payload_data[3];
1086 	unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;
1087 	unsigned int offset_num_regs;
1088 
1089 	packed_payload_size_bytes = param->num_blocks *
1090 				 cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
1091 	packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;
1092 
1093 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1094 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
1095 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
1096 
1097 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
1098 
1099 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1100 
1101 	/* Tests on XM must be after the XM header */
1102 	if (unpacked_mem_type == WMFW_ADSP2_XM) {
1103 		mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);
1104 
1105 		/* Round up to multiple of packed block length */
1106 		mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);
1107 	}
1108 
1109 	/* Add a single packed payload */
1110 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1111 					packed_mem_type, mem_offset_dsp_words,
1112 					packed_payload_data, packed_payload_size_bytes);
1113 	/*
1114 	 * Add three unpacked words to DSP memory right after the packed
1115 	 * payload words. Each unpacked word in its own payload.
1116 	 */
1117 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1118 					unpacked_mem_type,
1119 					mem_offset_dsp_words + packed_payload_size_dsp_words,
1120 					&unpacked_payload_data[0],
1121 					sizeof(unpacked_payload_data[0]));
1122 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1123 					unpacked_mem_type,
1124 					mem_offset_dsp_words + packed_payload_size_dsp_words + 1,
1125 					&unpacked_payload_data[1],
1126 					sizeof(unpacked_payload_data[1]));
1127 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1128 					unpacked_mem_type,
1129 					mem_offset_dsp_words + packed_payload_size_dsp_words + 2,
1130 					&unpacked_payload_data[2],
1131 					sizeof(unpacked_payload_data[2]));
1132 
1133 	/* Download the wmfw */
1134 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1135 	KUNIT_EXPECT_EQ(test,
1136 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1137 			0);
1138 	/*
1139 	 * Check that the packed payload was written correctly and drop
1140 	 * it from the regmap cache.
1141 	 */
1142 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *
1143 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1144 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1145 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1146 	KUNIT_EXPECT_EQ(test,
1147 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1148 					packed_payload_size_bytes),
1149 			0);
1150 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1151 
1152 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1153 
1154 	/*
1155 	 * Check that the unpacked words were written correctly and drop
1156 	 * them from the regmap cache. The unpacked words are offset
1157 	 * within unpacked register space by the number of DSP words
1158 	 * that were written in the packed payload.
1159 	 */
1160 	offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *
1161 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1162 	offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *
1163 			   cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1164 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1165 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1166 	KUNIT_EXPECT_EQ(test,
1167 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1168 					sizeof(unpacked_payload_data)),
1169 			0);
1170 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1171 
1172 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1173 
1174 	/* Drop expected writes and the cache should then be clean */
1175 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1176 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1177 }
1178 
1179 /*
1180  * Write XM/YM data that is one word longer than a packed block multiple,
1181  * and does not start on a packed alignment. Use one unpacked word
1182  * followed by a packed payload.
1183  */
wmfw_write_packed_1_unpacked_leading(struct kunit * test)1184 static void wmfw_write_packed_1_unpacked_leading(struct kunit *test)
1185 {
1186 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
1187 	struct cs_dsp_test *priv = test->priv;
1188 	struct cs_dsp_test_local *local = priv->local;
1189 	int packed_mem_type = param->mem_type;
1190 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1191 	unsigned int dsp_words_per_packed_block =
1192 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
1193 	unsigned int dsp_words_per_unpacked_block =
1194 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
1195 	unsigned int packed_payload_offset_dsp_words = 0;
1196 	struct firmware *wmfw;
1197 	unsigned int reg_addr;
1198 	void *packed_payload_data, *readback;
1199 	u32 unpacked_payload_data[1];
1200 	unsigned int packed_payload_size_bytes;
1201 	unsigned int offset_num_regs;
1202 
1203 	packed_payload_size_bytes = param->num_blocks *
1204 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
1205 
1206 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1207 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
1208 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
1209 
1210 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
1211 
1212 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1213 
1214 	/* Tests on XM must be after the XM header */
1215 	if (unpacked_mem_type == WMFW_ADSP2_XM)
1216 		packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /
1217 						   sizeof(u32);
1218 	/*
1219 	 * Leave space for an unaligned word before the packed block and
1220 	 * round the packed block start to multiple of packed block length.
1221 	 */
1222 	packed_payload_offset_dsp_words += 1;
1223 	packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,
1224 						  dsp_words_per_packed_block);
1225 
1226 	/* Add a single unpacked word right before the first word of packed data */
1227 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1228 					unpacked_mem_type,
1229 					packed_payload_offset_dsp_words - 1,
1230 					unpacked_payload_data, sizeof(unpacked_payload_data));
1231 
1232 	/* Add payload of packed data to the DSP memory after the unpacked word. */
1233 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1234 					packed_mem_type,
1235 					packed_payload_offset_dsp_words,
1236 					packed_payload_data, packed_payload_size_bytes);
1237 
1238 	/* Download the wmfw */
1239 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1240 	KUNIT_EXPECT_EQ(test,
1241 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1242 			0);
1243 	/*
1244 	 * Check that the packed payload was written correctly and drop
1245 	 * it from the regmap cache.
1246 	 */
1247 	offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *
1248 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1249 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1250 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1251 	KUNIT_EXPECT_EQ(test,
1252 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1253 					packed_payload_size_bytes),
1254 			0);
1255 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1256 
1257 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1258 
1259 	/*
1260 	 * Check that the unpacked word was written correctly and drop
1261 	 * it from the regmap cache.
1262 	 */
1263 	offset_num_regs = ((packed_payload_offset_dsp_words - 1) / dsp_words_per_unpacked_block) *
1264 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1265 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1266 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1267 	KUNIT_EXPECT_EQ(test,
1268 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1269 					sizeof(unpacked_payload_data)),
1270 			0);
1271 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1272 
1273 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1274 
1275 	/* Drop expected writes and the cache should then be clean */
1276 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1277 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1278 }
1279 
1280 /*
1281  * Write XM/YM data that is two words longer than a packed block multiple,
1282  * and does not start on a packed alignment. Use one payload of two unpacked
1283  * words followed by a packed payload.
1284  */
wmfw_write_packed_2_unpacked_leading(struct kunit * test)1285 static void wmfw_write_packed_2_unpacked_leading(struct kunit *test)
1286 {
1287 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
1288 	struct cs_dsp_test *priv = test->priv;
1289 	struct cs_dsp_test_local *local = priv->local;
1290 	int packed_mem_type = param->mem_type;
1291 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1292 	unsigned int dsp_words_per_packed_block =
1293 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
1294 	unsigned int dsp_words_per_unpacked_block =
1295 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
1296 	unsigned int packed_payload_offset_dsp_words = 0;
1297 	struct firmware *wmfw;
1298 	unsigned int reg_addr;
1299 	void *packed_payload_data, *readback;
1300 	u32 unpacked_payload_data[2];
1301 	unsigned int packed_payload_size_bytes;
1302 	unsigned int offset_num_regs;
1303 
1304 	packed_payload_size_bytes = param->num_blocks *
1305 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
1306 
1307 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1308 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
1309 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
1310 
1311 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
1312 
1313 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1314 
1315 	/* Tests on XM must be after the XM header */
1316 	if (unpacked_mem_type == WMFW_ADSP2_XM)
1317 		packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /
1318 						   sizeof(u32);
1319 	/*
1320 	 * Leave space for two unaligned words before the packed block and
1321 	 * round the packed block start to multiple of packed block length.
1322 	 */
1323 	packed_payload_offset_dsp_words += 2;
1324 	packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,
1325 						  dsp_words_per_packed_block);
1326 
1327 	/*
1328 	 * Add two unpacked words as a single payload right before the
1329 	 * first word of packed data
1330 	 */
1331 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1332 					unpacked_mem_type,
1333 					packed_payload_offset_dsp_words - 2,
1334 					unpacked_payload_data, sizeof(unpacked_payload_data));
1335 
1336 	/* Add payload of packed data to the DSP memory after the unpacked words. */
1337 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1338 					packed_mem_type,
1339 					packed_payload_offset_dsp_words,
1340 					packed_payload_data, packed_payload_size_bytes);
1341 
1342 	/* Download the wmfw */
1343 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1344 	KUNIT_EXPECT_EQ(test,
1345 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1346 			0);
1347 	/*
1348 	 * Check that the packed payload was written correctly and drop
1349 	 * it from the regmap cache.
1350 	 */
1351 	offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *
1352 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1353 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1354 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1355 	KUNIT_EXPECT_EQ(test,
1356 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1357 					packed_payload_size_bytes),
1358 			0);
1359 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1360 
1361 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1362 
1363 	/*
1364 	 * Check that the unpacked words were written correctly and drop
1365 	 * them from the regmap cache.
1366 	 */
1367 	offset_num_regs = ((packed_payload_offset_dsp_words - 2) / dsp_words_per_unpacked_block) *
1368 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1369 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1370 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1371 	KUNIT_EXPECT_EQ(test,
1372 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1373 					sizeof(unpacked_payload_data)),
1374 			0);
1375 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1376 
1377 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1378 
1379 	/* Drop expected writes and the cache should then be clean */
1380 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1381 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1382 }
1383 
1384 /*
1385  * Write XM/YM data that is three words longer than a packed block multiple,
1386  * and does not start on a packed alignment. Use one payload of three unpacked
1387  * words followed by a packed payload.
1388  */
wmfw_write_packed_3_unpacked_leading(struct kunit * test)1389 static void wmfw_write_packed_3_unpacked_leading(struct kunit *test)
1390 {
1391 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
1392 	struct cs_dsp_test *priv = test->priv;
1393 	struct cs_dsp_test_local *local = priv->local;
1394 	int packed_mem_type = param->mem_type;
1395 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1396 	unsigned int dsp_words_per_packed_block =
1397 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
1398 	unsigned int dsp_words_per_unpacked_block =
1399 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
1400 	unsigned int packed_payload_offset_dsp_words = 0;
1401 	struct firmware *wmfw;
1402 	unsigned int reg_addr;
1403 	void *packed_payload_data, *readback;
1404 	u32 unpacked_payload_data[3];
1405 	unsigned int packed_payload_size_bytes;
1406 	unsigned int offset_num_regs;
1407 
1408 	packed_payload_size_bytes = param->num_blocks *
1409 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
1410 
1411 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1412 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
1413 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
1414 
1415 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
1416 
1417 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1418 
1419 	/* Tests on XM must be after the XM header */
1420 	if (unpacked_mem_type == WMFW_ADSP2_XM)
1421 		packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /
1422 						   sizeof(u32);
1423 	/*
1424 	 * Leave space for three unaligned words before the packed block and
1425 	 * round the packed block start to multiple of packed block length.
1426 	 */
1427 	packed_payload_offset_dsp_words += 3;
1428 	packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,
1429 						  dsp_words_per_packed_block);
1430 
1431 	/*
1432 	 * Add three unpacked words as a single payload right before the
1433 	 * first word of packed data
1434 	 */
1435 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1436 					unpacked_mem_type,
1437 					packed_payload_offset_dsp_words - 3,
1438 					unpacked_payload_data, sizeof(unpacked_payload_data));
1439 
1440 	/* Add payload of packed data to the DSP memory after the unpacked words. */
1441 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1442 					packed_mem_type,
1443 					packed_payload_offset_dsp_words,
1444 					packed_payload_data, packed_payload_size_bytes);
1445 
1446 	/* Download the wmfw */
1447 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1448 	KUNIT_EXPECT_EQ(test,
1449 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1450 			0);
1451 	/*
1452 	 * Check that the packed payload was written correctly and drop
1453 	 * it from the regmap cache.
1454 	 */
1455 	offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *
1456 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1457 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1458 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1459 	KUNIT_EXPECT_EQ(test,
1460 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1461 					packed_payload_size_bytes),
1462 			0);
1463 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1464 
1465 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1466 
1467 	/*
1468 	 * Check that the unpacked words were written correctly and drop
1469 	 * them from the regmap cache.
1470 	 */
1471 	offset_num_regs = ((packed_payload_offset_dsp_words - 3) / dsp_words_per_unpacked_block) *
1472 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1473 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1474 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1475 	KUNIT_EXPECT_EQ(test,
1476 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1477 					sizeof(unpacked_payload_data)),
1478 			0);
1479 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1480 
1481 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1482 
1483 	/* Drop expected writes and the cache should then be clean */
1484 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1485 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1486 }
1487 
1488 /*
1489  * Write XM/YM data that is two words longer than a packed block multiple,
1490  * and does not start on a packed alignment. Use two payloads of one unpacked
1491  * word each, followed by a packed payload.
1492  */
wmfw_write_packed_2_single_unpacked_leading(struct kunit * test)1493 static void wmfw_write_packed_2_single_unpacked_leading(struct kunit *test)
1494 {
1495 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
1496 	struct cs_dsp_test *priv = test->priv;
1497 	struct cs_dsp_test_local *local = priv->local;
1498 	int packed_mem_type = param->mem_type;
1499 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1500 	unsigned int dsp_words_per_packed_block =
1501 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
1502 	unsigned int dsp_words_per_unpacked_block =
1503 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
1504 	unsigned int packed_payload_offset_dsp_words = 0;
1505 	struct firmware *wmfw;
1506 	unsigned int reg_addr;
1507 	void *packed_payload_data, *readback;
1508 	u32 unpacked_payload_data[2];
1509 	unsigned int packed_payload_size_bytes;
1510 	unsigned int offset_num_regs;
1511 
1512 	packed_payload_size_bytes = param->num_blocks *
1513 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
1514 
1515 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1516 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
1517 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
1518 
1519 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
1520 
1521 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1522 
1523 	/* Tests on XM must be after the XM header */
1524 	if (unpacked_mem_type == WMFW_ADSP2_XM)
1525 		packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /
1526 						   sizeof(u32);
1527 	/*
1528 	 * Leave space for two unaligned words before the packed block and
1529 	 * round the packed block start to multiple of packed block length.
1530 	 */
1531 	packed_payload_offset_dsp_words += 2;
1532 	packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,
1533 						  dsp_words_per_packed_block);
1534 
1535 	/*
1536 	 * Add two unpacked words as two payloads each containing a single
1537 	 * unpacked word.
1538 	 */
1539 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1540 					unpacked_mem_type,
1541 					packed_payload_offset_dsp_words - 2,
1542 					&unpacked_payload_data[0],
1543 					sizeof(unpacked_payload_data[0]));
1544 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1545 					unpacked_mem_type,
1546 					packed_payload_offset_dsp_words - 1,
1547 					&unpacked_payload_data[1],
1548 					sizeof(unpacked_payload_data[1]));
1549 
1550 	/* Add payload of packed data to the DSP memory after the unpacked words. */
1551 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1552 					packed_mem_type,
1553 					packed_payload_offset_dsp_words,
1554 					packed_payload_data, packed_payload_size_bytes);
1555 
1556 	/* Download the wmfw */
1557 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1558 	KUNIT_EXPECT_EQ(test,
1559 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1560 			0);
1561 	/*
1562 	 * Check that the packed payload was written correctly and drop
1563 	 * it from the regmap cache.
1564 	 */
1565 	offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *
1566 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1567 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1568 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1569 	KUNIT_EXPECT_EQ(test,
1570 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1571 					packed_payload_size_bytes),
1572 			0);
1573 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1574 
1575 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1576 
1577 	/*
1578 	 * Check that the unpacked words were written correctly and drop
1579 	 * them from the regmap cache.
1580 	 */
1581 	offset_num_regs = ((packed_payload_offset_dsp_words - 2) / dsp_words_per_unpacked_block) *
1582 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1583 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1584 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1585 	KUNIT_EXPECT_EQ(test,
1586 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1587 					sizeof(unpacked_payload_data)),
1588 			0);
1589 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1590 
1591 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1592 
1593 	/* Drop expected writes and the cache should then be clean */
1594 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1595 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1596 }
1597 
1598 /*
1599  * Write XM/YM data that is three words longer than a packed block multiple,
1600  * and does not start on a packed alignment. Use three payloads of one unpacked
1601  * word each, followed by a packed payload.
1602  */
wmfw_write_packed_3_single_unpacked_leading(struct kunit * test)1603 static void wmfw_write_packed_3_single_unpacked_leading(struct kunit *test)
1604 {
1605 	const struct cs_dsp_wmfw_test_param *param = test->param_value;
1606 	struct cs_dsp_test *priv = test->priv;
1607 	struct cs_dsp_test_local *local = priv->local;
1608 	int packed_mem_type = param->mem_type;
1609 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1610 	unsigned int dsp_words_per_packed_block =
1611 		cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);
1612 	unsigned int dsp_words_per_unpacked_block =
1613 		cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);
1614 	unsigned int packed_payload_offset_dsp_words = 0;
1615 	struct firmware *wmfw;
1616 	unsigned int reg_addr;
1617 	void *packed_payload_data, *readback;
1618 	u32 unpacked_payload_data[3];
1619 	unsigned int packed_payload_size_bytes;
1620 	unsigned int offset_num_regs;
1621 
1622 	packed_payload_size_bytes = param->num_blocks *
1623 				    cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);
1624 
1625 	packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1626 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);
1627 	get_random_bytes(packed_payload_data, packed_payload_size_bytes);
1628 
1629 	get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));
1630 
1631 	readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);
1632 
1633 	/* Tests on XM must be after the XM header */
1634 	if (unpacked_mem_type == WMFW_ADSP2_XM)
1635 		packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /
1636 						   sizeof(u32);
1637 	/*
1638 	 * Leave space for two unaligned words before the packed block and
1639 	 * round the packed block start to multiple of packed block length.
1640 	 */
1641 	packed_payload_offset_dsp_words += 3;
1642 	packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,
1643 						  dsp_words_per_packed_block);
1644 
1645 	/*
1646 	 * Add three unpacked words as three payloads each containing a single
1647 	 * unpacked word.
1648 	 */
1649 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1650 					unpacked_mem_type,
1651 					packed_payload_offset_dsp_words - 3,
1652 					&unpacked_payload_data[0],
1653 					sizeof(unpacked_payload_data[0]));
1654 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1655 					unpacked_mem_type,
1656 					packed_payload_offset_dsp_words - 2,
1657 					&unpacked_payload_data[1],
1658 					sizeof(unpacked_payload_data[1]));
1659 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1660 					unpacked_mem_type,
1661 					packed_payload_offset_dsp_words - 1,
1662 					&unpacked_payload_data[2],
1663 					sizeof(unpacked_payload_data[2]));
1664 
1665 	/* Add payload of packed data to the DSP memory after the unpacked words. */
1666 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1667 					packed_mem_type,
1668 					packed_payload_offset_dsp_words,
1669 					packed_payload_data, packed_payload_size_bytes);
1670 
1671 	/* Download the wmfw */
1672 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1673 	KUNIT_EXPECT_EQ(test,
1674 			cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),
1675 			0);
1676 	/*
1677 	 * Check that the packed payload was written correctly and drop
1678 	 * it from the regmap cache.
1679 	 */
1680 	offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *
1681 			  cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);
1682 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);
1683 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1684 	KUNIT_EXPECT_EQ(test,
1685 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1686 					packed_payload_size_bytes),
1687 			0);
1688 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);
1689 
1690 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);
1691 
1692 	/*
1693 	 * Check that the unpacked words were written correctly and drop
1694 	 * them from the regmap cache.
1695 	 */
1696 	offset_num_regs = ((packed_payload_offset_dsp_words - 3) / dsp_words_per_unpacked_block) *
1697 			  cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);
1698 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);
1699 	reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);
1700 	KUNIT_EXPECT_EQ(test,
1701 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1702 					sizeof(unpacked_payload_data)),
1703 			0);
1704 	KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));
1705 
1706 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));
1707 
1708 	/* Drop expected writes and the cache should then be clean */
1709 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1710 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1711 }
1712 
1713 /* Load a wmfw containing multiple info blocks */
wmfw_load_with_info(struct kunit * test)1714 static void wmfw_load_with_info(struct kunit *test)
1715 {
1716 	struct cs_dsp_test *priv = test->priv;
1717 	struct cs_dsp_test_local *local = priv->local;
1718 	struct firmware *wmfw;
1719 	unsigned int reg_addr;
1720 	u8 *payload_data, *readback;
1721 	char *infobuf;
1722 	const unsigned int payload_size_bytes = 48;
1723 	int ret;
1724 
1725 	payload_data = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);
1726 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);
1727 	get_random_bytes(payload_data, payload_size_bytes);
1728 
1729 	readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);
1730 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1731 
1732 	/* Add a couple of info blocks at the start of the wmfw */
1733 	cs_dsp_mock_wmfw_add_info(local->wmfw_builder, "This is a timestamp");
1734 	cs_dsp_mock_wmfw_add_info(local->wmfw_builder, "This is some more info");
1735 
1736 	/* Add a single payload */
1737 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1738 					WMFW_ADSP2_YM, 0,
1739 					payload_data, payload_size_bytes);
1740 
1741 	/* Add a bigger info block then another small one*/
1742 	infobuf = kunit_kzalloc(test, 512, GFP_KERNEL);
1743 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, infobuf);
1744 
1745 	for (; strlcat(infobuf, "Waffle{Blah}\n", 512) < 512;)
1746 		;
1747 
1748 	cs_dsp_mock_wmfw_add_info(local->wmfw_builder, infobuf);
1749 	cs_dsp_mock_wmfw_add_info(local->wmfw_builder, "Another block of info");
1750 
1751 	/* Add another payload */
1752 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1753 					WMFW_ADSP2_YM, 64,
1754 					payload_data, payload_size_bytes);
1755 
1756 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1757 
1758 	ret = cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc");
1759 	KUNIT_EXPECT_EQ_MSG(test, ret, 0, "cs_dsp_power_up failed: %d\n", ret);
1760 
1761 	/* Check first payload was written */
1762 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
1763 	KUNIT_EXPECT_EQ(test,
1764 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),
1765 			0);
1766 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
1767 
1768 	/* Check second payload was written */
1769 	reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * 64;
1770 	KUNIT_EXPECT_EQ(test,
1771 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),
1772 			0);
1773 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);
1774 }
1775 
cs_dsp_wmfw_test_common_init(struct kunit * test,struct cs_dsp * dsp,int wmfw_version)1776 static int cs_dsp_wmfw_test_common_init(struct kunit *test, struct cs_dsp *dsp,
1777 					int wmfw_version)
1778 {
1779 	struct cs_dsp_test *priv;
1780 	struct cs_dsp_test_local *local;
1781 	struct device *test_dev;
1782 	int ret;
1783 
1784 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
1785 	if (!priv)
1786 		return -ENOMEM;
1787 
1788 	local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
1789 	if (!local)
1790 		return -ENOMEM;
1791 
1792 	priv->test = test;
1793 	priv->dsp = dsp;
1794 	test->priv = priv;
1795 	priv->local = local;
1796 	priv->local->wmfw_version = wmfw_version;
1797 
1798 	/* Create dummy struct device */
1799 	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
1800 	if (IS_ERR(test_dev))
1801 		return PTR_ERR(test_dev);
1802 
1803 	dsp->dev = get_device(test_dev);
1804 	if (!dsp->dev)
1805 		return -ENODEV;
1806 
1807 	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
1808 	if (ret)
1809 		return ret;
1810 
1811 	dev_set_drvdata(dsp->dev, priv);
1812 
1813 	/* Allocate regmap */
1814 	ret = cs_dsp_mock_regmap_init(priv);
1815 	if (ret)
1816 		return ret;
1817 
1818 	/*
1819 	 * There must always be a XM header with at least 1 algorithm, so create
1820 	 * a dummy one that tests can use and extract it to a data payload.
1821 	 */
1822 	local->xm_header = cs_dsp_create_mock_xm_header(priv,
1823 							cs_dsp_wmfw_test_mock_algs,
1824 							ARRAY_SIZE(cs_dsp_wmfw_test_mock_algs));
1825 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
1826 
1827 	local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, priv->local->wmfw_version);
1828 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder);
1829 
1830 	/* Add dummy XM header payload to wmfw */
1831 	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1832 					WMFW_ADSP2_XM, 0,
1833 					local->xm_header->blob_data,
1834 					local->xm_header->blob_size_bytes);
1835 
1836 	/* Init cs_dsp */
1837 	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
1838 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
1839 
1840 	switch (dsp->type) {
1841 	case WMFW_ADSP2:
1842 		ret = cs_dsp_adsp2_init(dsp);
1843 		break;
1844 	case WMFW_HALO:
1845 		ret = cs_dsp_halo_init(dsp);
1846 		break;
1847 	default:
1848 		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
1849 		return -EINVAL;
1850 	}
1851 
1852 	if (ret)
1853 		return ret;
1854 
1855 	/* Automatically call cs_dsp_remove() when test case ends */
1856 	return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
1857 }
1858 
cs_dsp_wmfw_test_halo_init(struct kunit * test)1859 static int cs_dsp_wmfw_test_halo_init(struct kunit *test)
1860 {
1861 	struct cs_dsp *dsp;
1862 
1863 	/* Fill in cs_dsp and initialize */
1864 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1865 	if (!dsp)
1866 		return -ENOMEM;
1867 
1868 	dsp->num = 1;
1869 	dsp->type = WMFW_HALO;
1870 	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
1871 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
1872 	dsp->base = cs_dsp_mock_halo_core_base;
1873 	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
1874 
1875 	return cs_dsp_wmfw_test_common_init(test, dsp, 3);
1876 }
1877 
cs_dsp_wmfw_test_adsp2_32bit_init(struct kunit * test,int wmfw_ver)1878 static int cs_dsp_wmfw_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
1879 {
1880 	struct cs_dsp *dsp;
1881 
1882 	/* Fill in cs_dsp and initialize */
1883 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1884 	if (!dsp)
1885 		return -ENOMEM;
1886 
1887 	dsp->num = 1;
1888 	dsp->type = WMFW_ADSP2;
1889 	dsp->rev = 1;
1890 	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
1891 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
1892 	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
1893 
1894 	return cs_dsp_wmfw_test_common_init(test, dsp, wmfw_ver);
1895 }
1896 
cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init(struct kunit * test)1897 static int cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init(struct kunit *test)
1898 {
1899 	return cs_dsp_wmfw_test_adsp2_32bit_init(test, 0);
1900 }
1901 
cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init(struct kunit * test)1902 static int cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init(struct kunit *test)
1903 {
1904 	return cs_dsp_wmfw_test_adsp2_32bit_init(test, 1);
1905 }
1906 
cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init(struct kunit * test)1907 static int cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init(struct kunit *test)
1908 {
1909 	return cs_dsp_wmfw_test_adsp2_32bit_init(test, 2);
1910 }
1911 
cs_dsp_wmfw_test_adsp2_16bit_init(struct kunit * test,int wmfw_ver)1912 static int cs_dsp_wmfw_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
1913 {
1914 	struct cs_dsp *dsp;
1915 
1916 	/* Fill in cs_dsp and initialize */
1917 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1918 	if (!dsp)
1919 		return -ENOMEM;
1920 
1921 	dsp->num = 1;
1922 	dsp->type = WMFW_ADSP2;
1923 	dsp->rev = 0;
1924 	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
1925 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
1926 	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
1927 
1928 	return cs_dsp_wmfw_test_common_init(test, dsp, wmfw_ver);
1929 }
1930 
cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init(struct kunit * test)1931 static int cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init(struct kunit *test)
1932 {
1933 	return cs_dsp_wmfw_test_adsp2_16bit_init(test, 0);
1934 }
1935 
cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init(struct kunit * test)1936 static int cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init(struct kunit *test)
1937 {
1938 	return cs_dsp_wmfw_test_adsp2_16bit_init(test, 1);
1939 }
1940 
cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init(struct kunit * test)1941 static int cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init(struct kunit *test)
1942 {
1943 	return cs_dsp_wmfw_test_adsp2_16bit_init(test, 2);
1944 }
1945 
cs_dsp_mem_param_desc(const struct cs_dsp_wmfw_test_param * param,char * desc)1946 static void cs_dsp_mem_param_desc(const struct cs_dsp_wmfw_test_param *param, char *desc)
1947 {
1948 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s num_blocks:%u",
1949 		 cs_dsp_mem_region_name(param->mem_type),
1950 		 param->num_blocks);
1951 }
1952 
1953 static const struct cs_dsp_wmfw_test_param adsp2_all_num_blocks_param_cases[] = {
1954 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 1 },
1955 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 2 },
1956 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 3 },
1957 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 4 },
1958 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 5 },
1959 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 6 },
1960 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 12 },
1961 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 13 },
1962 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 14 },
1963 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 15 },
1964 	{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 16 },
1965 
1966 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 1 },
1967 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 2 },
1968 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 3 },
1969 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 4 },
1970 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 5 },
1971 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 6 },
1972 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 12 },
1973 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 13 },
1974 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 14 },
1975 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 15 },
1976 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 16 },
1977 
1978 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 1 },
1979 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 2 },
1980 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 3 },
1981 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 4 },
1982 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 5 },
1983 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 6 },
1984 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 12 },
1985 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 13 },
1986 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 14 },
1987 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 15 },
1988 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 16 },
1989 
1990 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 1 },
1991 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 2 },
1992 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 3 },
1993 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 4 },
1994 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 5 },
1995 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 6 },
1996 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 12 },
1997 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 13 },
1998 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 14 },
1999 	{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 15 },
2000 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 16 },
2001 };
2002 
2003 KUNIT_ARRAY_PARAM(adsp2_all_num_blocks,
2004 		  adsp2_all_num_blocks_param_cases,
2005 		  cs_dsp_mem_param_desc);
2006 
2007 static const struct cs_dsp_wmfw_test_param halo_all_num_blocks_param_cases[] = {
2008 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 1 },
2009 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 2 },
2010 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 3 },
2011 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 4 },
2012 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 5 },
2013 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 6 },
2014 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 12 },
2015 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 13 },
2016 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 14 },
2017 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 15 },
2018 	{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 16 },
2019 
2020 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 1 },
2021 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 2 },
2022 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 3 },
2023 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 4 },
2024 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 5 },
2025 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 6 },
2026 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 12 },
2027 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 13 },
2028 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 14 },
2029 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 15 },
2030 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 16 },
2031 
2032 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 1 },
2033 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 2 },
2034 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 3 },
2035 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 4 },
2036 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 5 },
2037 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 6 },
2038 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 12 },
2039 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 13 },
2040 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 14 },
2041 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 15 },
2042 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 16 },
2043 
2044 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 1 },
2045 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 2 },
2046 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 3 },
2047 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 4 },
2048 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 5 },
2049 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 6 },
2050 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 12 },
2051 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 13 },
2052 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 14 },
2053 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 15 },
2054 	{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 16 },
2055 
2056 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 1 },
2057 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 2 },
2058 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 3 },
2059 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 4 },
2060 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 5 },
2061 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 6 },
2062 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 12 },
2063 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 13 },
2064 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 14 },
2065 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 15 },
2066 	{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 16 },
2067 };
2068 
2069 KUNIT_ARRAY_PARAM(halo_all_num_blocks,
2070 		  halo_all_num_blocks_param_cases,
2071 		  cs_dsp_mem_param_desc);
2072 
2073 static const struct cs_dsp_wmfw_test_param packed_xy_num_blocks_param_cases[] = {
2074 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 1 },
2075 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 2 },
2076 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 3 },
2077 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 4 },
2078 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 5 },
2079 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 6 },
2080 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 12 },
2081 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 13 },
2082 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 14 },
2083 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 15 },
2084 	{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 16 },
2085 
2086 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 1 },
2087 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 2 },
2088 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 3 },
2089 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 4 },
2090 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 5 },
2091 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 6 },
2092 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 12 },
2093 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 13 },
2094 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 14 },
2095 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 15 },
2096 	{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 16 },
2097 };
2098 
2099 KUNIT_ARRAY_PARAM(packed_xy_num_blocks,
2100 		  packed_xy_num_blocks_param_cases,
2101 		  cs_dsp_mem_param_desc);
2102 
2103 static struct kunit_case cs_dsp_wmfw_test_cases_halo[] = {
2104 	KUNIT_CASE(wmfw_write_xm_header_unpacked),
2105 
2106 	KUNIT_CASE_PARAM(wmfw_write_one_payload,
2107 			 halo_all_num_blocks_gen_params),
2108 	KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads,
2109 			 halo_all_num_blocks_gen_params),
2110 	KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads_reverse,
2111 			 halo_all_num_blocks_gen_params),
2112 	KUNIT_CASE_PARAM(wmfw_write_multiple_payloads_sparse_unordered,
2113 			 halo_all_num_blocks_gen_params),
2114 
2115 	KUNIT_CASE(wmfw_write_all_packed_pm),
2116 	KUNIT_CASE(wmfw_write_multiple_packed_unpacked_mem),
2117 
2118 	KUNIT_CASE_PARAM(wmfw_write_packed_1_unpacked_trailing,
2119 			 packed_xy_num_blocks_gen_params),
2120 	KUNIT_CASE_PARAM(wmfw_write_packed_2_unpacked_trailing,
2121 			 packed_xy_num_blocks_gen_params),
2122 	KUNIT_CASE_PARAM(wmfw_write_packed_3_unpacked_trailing,
2123 			 packed_xy_num_blocks_gen_params),
2124 	KUNIT_CASE_PARAM(wmfw_write_packed_2_single_unpacked_trailing,
2125 			 packed_xy_num_blocks_gen_params),
2126 	KUNIT_CASE_PARAM(wmfw_write_packed_3_single_unpacked_trailing,
2127 			 packed_xy_num_blocks_gen_params),
2128 	KUNIT_CASE_PARAM(wmfw_write_packed_1_unpacked_leading,
2129 			 packed_xy_num_blocks_gen_params),
2130 	KUNIT_CASE_PARAM(wmfw_write_packed_2_unpacked_leading,
2131 			 packed_xy_num_blocks_gen_params),
2132 	KUNIT_CASE_PARAM(wmfw_write_packed_3_unpacked_leading,
2133 			 packed_xy_num_blocks_gen_params),
2134 	KUNIT_CASE_PARAM(wmfw_write_packed_2_single_unpacked_leading,
2135 			 packed_xy_num_blocks_gen_params),
2136 	KUNIT_CASE_PARAM(wmfw_write_packed_3_single_unpacked_leading,
2137 			 packed_xy_num_blocks_gen_params),
2138 
2139 	KUNIT_CASE(wmfw_load_with_info),
2140 
2141 	{ } /* terminator */
2142 };
2143 
2144 static struct kunit_case cs_dsp_wmfw_test_cases_adsp2[] = {
2145 	KUNIT_CASE(wmfw_write_xm_header_unpacked),
2146 	KUNIT_CASE_PARAM(wmfw_write_one_payload,
2147 			 adsp2_all_num_blocks_gen_params),
2148 	KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads,
2149 			 adsp2_all_num_blocks_gen_params),
2150 	KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads_reverse,
2151 			 adsp2_all_num_blocks_gen_params),
2152 	KUNIT_CASE_PARAM(wmfw_write_multiple_payloads_sparse_unordered,
2153 			 adsp2_all_num_blocks_gen_params),
2154 
2155 	KUNIT_CASE(wmfw_write_all_unpacked_pm),
2156 	KUNIT_CASE(wmfw_write_multiple_unpacked_mem),
2157 
2158 	KUNIT_CASE(wmfw_load_with_info),
2159 
2160 	{ } /* terminator */
2161 };
2162 
2163 static struct kunit_suite cs_dsp_wmfw_test_halo = {
2164 	.name = "cs_dsp_wmfwV3_halo",
2165 	.init = cs_dsp_wmfw_test_halo_init,
2166 	.test_cases = cs_dsp_wmfw_test_cases_halo,
2167 };
2168 
2169 static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw0 = {
2170 	.name = "cs_dsp_wmfwV0_adsp2_32bit",
2171 	.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init,
2172 	.test_cases = cs_dsp_wmfw_test_cases_adsp2,
2173 };
2174 
2175 static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw1 = {
2176 	.name = "cs_dsp_wmfwV1_adsp2_32bit",
2177 	.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init,
2178 	.test_cases = cs_dsp_wmfw_test_cases_adsp2,
2179 };
2180 
2181 static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw2 = {
2182 	.name = "cs_dsp_wmfwV2_adsp2_32bit",
2183 	.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init,
2184 	.test_cases = cs_dsp_wmfw_test_cases_adsp2,
2185 };
2186 
2187 static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw0 = {
2188 	.name = "cs_dsp_wmfwV0_adsp2_16bit",
2189 	.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init,
2190 	.test_cases = cs_dsp_wmfw_test_cases_adsp2,
2191 };
2192 
2193 static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw1 = {
2194 	.name = "cs_dsp_wmfwV1_adsp2_16bit",
2195 	.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init,
2196 	.test_cases = cs_dsp_wmfw_test_cases_adsp2,
2197 };
2198 
2199 static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw2 = {
2200 	.name = "cs_dsp_wmfwV2_adsp2_16bit",
2201 	.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init,
2202 	.test_cases = cs_dsp_wmfw_test_cases_adsp2,
2203 };
2204 
2205 kunit_test_suites(&cs_dsp_wmfw_test_halo,
2206 		  &cs_dsp_wmfw_test_adsp2_32bit_wmfw0,
2207 		  &cs_dsp_wmfw_test_adsp2_32bit_wmfw1,
2208 		  &cs_dsp_wmfw_test_adsp2_32bit_wmfw2,
2209 		  &cs_dsp_wmfw_test_adsp2_16bit_wmfw0,
2210 		  &cs_dsp_wmfw_test_adsp2_16bit_wmfw1,
2211 		  &cs_dsp_wmfw_test_adsp2_16bit_wmfw2);
2212