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