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