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