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