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