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