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