Path: blob/master/drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c
52653 views
// SPDX-License-Identifier: GPL-2.0-only1//2// KUnit tests for cs_dsp.3//4// Copyright (C) 2024 Cirrus Logic, Inc. and5// Cirrus Logic International Semiconductor Ltd.6//78#include <kunit/device.h>9#include <kunit/resource.h>10#include <kunit/test.h>11#include <linux/build_bug.h>12#include <linux/firmware/cirrus/cs_dsp.h>13#include <linux/firmware/cirrus/cs_dsp_test_utils.h>14#include <linux/firmware/cirrus/wmfw.h>15#include <linux/random.h>16#include <linux/regmap.h>17#include <linux/string.h>18#include <linux/vmalloc.h>1920#include "../cs_dsp.h"2122/*23* Test method is:24*25* 1) Create a mock regmap in cache-only mode so that all writes will be cached.26* 2) Create dummy wmfw file.27* 3) Call cs_dsp_power_up() with the bin file.28* 4) Readback the cached value of registers that should have been written and29* check they have the correct value.30* 5) All the registers that are expected to have been written are dropped from31* the cache. This should leave the cache clean.32* 6) If the cache is still dirty there have been unexpected writes.33*/3435KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)36KUNIT_DEFINE_ACTION_WRAPPER(_vfree_wrapper, vfree, void *)37KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)3839struct cs_dsp_test_local {40struct cs_dsp_mock_xm_header *xm_header;41struct cs_dsp_mock_wmfw_builder *wmfw_builder;42int wmfw_version;43};4445struct cs_dsp_wmfw_test_param {46unsigned int num_blocks;47int mem_type;48};4950static const struct cs_dsp_mock_alg_def cs_dsp_wmfw_test_mock_algs[] = {51{52.id = 0xfafa,53.ver = 0x100000,54.xm_size_words = 164,55.ym_size_words = 164,56.zm_size_words = 164,57},58};5960/*61* wmfw that writes the XM header.62* cs_dsp always reads this back from unpacked XM.63*/64static void wmfw_write_xm_header_unpacked(struct kunit *test)65{66struct cs_dsp_test *priv = test->priv;67struct cs_dsp_test_local *local = priv->local;68struct firmware *wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);69unsigned int reg_addr;70u8 *readback;7172/* XM header payload was added to wmfw by test case init function */7374KUNIT_EXPECT_EQ(test,75cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),760);7778/* Read raw so endianness and register width don't matter */79readback = kunit_kzalloc(test, local->xm_header->blob_size_bytes, GFP_KERNEL);80KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);8182reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM);83KUNIT_EXPECT_EQ(test,84regmap_raw_read(priv->dsp->regmap, reg_addr, readback,85local->xm_header->blob_size_bytes),860);87KUNIT_EXPECT_MEMEQ(test, readback, local->xm_header->blob_data,88local->xm_header->blob_size_bytes);8990/* Drop expected writes and the cache should then be clean */91cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);92KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));93}9495/* Write one payload of length param->num_blocks */96static void wmfw_write_one_payload(struct kunit *test)97{98const struct cs_dsp_wmfw_test_param *param = test->param_value;99struct cs_dsp_test *priv = test->priv;100struct cs_dsp_test_local *local = priv->local;101struct firmware *wmfw;102unsigned int reg_addr;103u8 *payload_data, *readback;104unsigned int mem_offset_dsp_words = 0;105unsigned int payload_size_bytes;106107payload_size_bytes = param->num_blocks *108cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);109110/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */111do {112payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);113} while (payload_size_bytes % 4);114115payload_data = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);116KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);117get_random_bytes(payload_data, payload_size_bytes);118119readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);120KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);121122/* Tests on XM must be after the XM header */123if (param->mem_type == WMFW_ADSP2_XM)124mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);125126/* Add a single payload */127cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,128param->mem_type, mem_offset_dsp_words,129payload_data, payload_size_bytes);130131wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);132133KUNIT_EXPECT_EQ(test,134cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),1350);136137reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);138reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;139KUNIT_EXPECT_EQ(test,140regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),1410);142KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);143144/* Drop expected writes and the cache should then be clean */145cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);146cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);147KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));148}149150/* Write several smallest possible payloads for the given memory type */151static void wmfw_write_multiple_oneblock_payloads(struct kunit *test)152{153const struct cs_dsp_wmfw_test_param *param = test->param_value;154struct cs_dsp_test *priv = test->priv;155struct cs_dsp_test_local *local = priv->local;156struct firmware *wmfw;157unsigned int reg_addr;158u8 *payload_data, *readback;159unsigned int mem_offset_dsp_words = 0;160unsigned int payload_size_bytes, payload_size_dsp_words;161const unsigned int num_payloads = param->num_blocks;162int i;163164/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */165payload_size_dsp_words = 0;166payload_size_bytes = 0;167do {168payload_size_dsp_words += cs_dsp_mock_reg_block_length_dsp_words(priv,169param->mem_type);170payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);171} while (payload_size_bytes % 4);172173payload_data = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);174KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);175176readback = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);177KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);178179get_random_bytes(payload_data, num_payloads * payload_size_bytes);180181/* Tests on XM must be after the XM header */182if (param->mem_type == WMFW_ADSP2_XM)183mem_offset_dsp_words += local->xm_header->blob_size_bytes / payload_size_bytes;184185/* Add multiple payloads of one block each */186for (i = 0; i < num_payloads; ++i) {187cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,188param->mem_type,189mem_offset_dsp_words + (i * payload_size_dsp_words),190&payload_data[i * payload_size_bytes],191payload_size_bytes);192}193194wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);195196KUNIT_EXPECT_EQ(test,197cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),1980);199200reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);201reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;202KUNIT_EXPECT_EQ(test,203regmap_raw_read(priv->dsp->regmap, reg_addr, readback,204num_payloads * payload_size_bytes),2050);206KUNIT_EXPECT_MEMEQ(test, readback, payload_data, num_payloads * payload_size_bytes);207208/* Drop expected writes and the cache should then be clean */209cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, num_payloads * payload_size_bytes);210cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);211KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));212}213214/*215* Write several smallest possible payloads of the given memory type216* in reverse address order217*/218static void wmfw_write_multiple_oneblock_payloads_reverse(struct kunit *test)219{220const struct cs_dsp_wmfw_test_param *param = test->param_value;221struct cs_dsp_test *priv = test->priv;222struct cs_dsp_test_local *local = priv->local;223struct firmware *wmfw;224unsigned int reg_addr;225u8 *payload_data, *readback;226unsigned int mem_offset_dsp_words = 0;227unsigned int payload_size_bytes, payload_size_dsp_words;228const unsigned int num_payloads = param->num_blocks;229int i;230231/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */232payload_size_dsp_words = 0;233payload_size_bytes = 0;234do {235payload_size_dsp_words += cs_dsp_mock_reg_block_length_dsp_words(priv,236param->mem_type);237payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);238} while (payload_size_bytes % 4);239240payload_data = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);241KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);242243readback = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);244KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);245246get_random_bytes(payload_data, num_payloads * payload_size_bytes);247248/* Tests on XM must be after the XM header */249if (param->mem_type == WMFW_ADSP2_XM)250mem_offset_dsp_words += local->xm_header->blob_size_bytes / payload_size_bytes;251252/* Add multiple payloads of one block each */253for (i = num_payloads - 1; i >= 0; --i) {254cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,255param->mem_type,256mem_offset_dsp_words + (i * payload_size_dsp_words),257&payload_data[i * payload_size_bytes],258payload_size_bytes);259}260261wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);262263KUNIT_EXPECT_EQ(test,264cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),2650);266267reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);268reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;269KUNIT_EXPECT_EQ(test,270regmap_raw_read(priv->dsp->regmap, reg_addr, readback,271num_payloads * payload_size_bytes),2720);273KUNIT_EXPECT_MEMEQ(test, readback, payload_data, num_payloads * payload_size_bytes);274275/* Drop expected writes and the cache should then be clean */276cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, num_payloads * payload_size_bytes);277cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);278KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));279}280281/*282* Write multiple payloads of length param->num_blocks.283* The payloads are not in address order and collectively do not patch284* a contiguous block of memory.285*/286static void wmfw_write_multiple_payloads_sparse_unordered(struct kunit *test)287{288static const unsigned int random_offsets[] = {28911, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,29054, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,29129, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22292};293const struct cs_dsp_wmfw_test_param *param = test->param_value;294struct cs_dsp_test *priv = test->priv;295struct cs_dsp_test_local *local = priv->local;296struct firmware *wmfw;297unsigned int reg_addr;298u8 *payload_data, *readback;299unsigned int mem_offset_dsp_words = 0;300unsigned int payload_size_bytes, payload_size_dsp_words;301const int num_payloads = ARRAY_SIZE(random_offsets);302int i;303304payload_size_bytes = param->num_blocks *305cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);306payload_size_dsp_words = param->num_blocks *307cs_dsp_mock_reg_block_length_dsp_words(priv, param->mem_type);308309/* payloads must be a multiple of 4 bytes and a whole number of DSP registers */310do {311payload_size_dsp_words += cs_dsp_mock_reg_block_length_dsp_words(priv,312param->mem_type);313payload_size_bytes += cs_dsp_mock_reg_block_length_bytes(priv, param->mem_type);314} while (payload_size_bytes % 4);315316payload_data = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);317KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);318get_random_bytes(payload_data, payload_size_bytes);319320readback = kunit_kcalloc(test, num_payloads, payload_size_bytes, GFP_KERNEL);321KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);322323/* Tests on XM must be after the XM header */324if (param->mem_type == WMFW_ADSP2_XM)325mem_offset_dsp_words += local->xm_header->blob_size_bytes / payload_size_bytes;326327/* Add multiple payloads of one block each at "random" locations */328for (i = 0; i < num_payloads; ++i) {329unsigned int offset = random_offsets[i] * payload_size_dsp_words;330331cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,332param->mem_type,333mem_offset_dsp_words + offset,334&payload_data[i * payload_size_bytes],335payload_size_bytes);336}337338wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);339340KUNIT_EXPECT_EQ(test,341cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),3420);343344for (i = 0; i < num_payloads; ++i) {345unsigned int offset_num_regs = (random_offsets[i] * payload_size_bytes) /346regmap_get_val_bytes(priv->dsp->regmap);347reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);348reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);349reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * mem_offset_dsp_words;350KUNIT_EXPECT_EQ(test,351regmap_raw_read(priv->dsp->regmap, reg_addr,352&readback[i * payload_size_bytes],353payload_size_bytes),3540);355356cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);357}358359KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);360361/* Drop expected writes and the cache should then be clean */362cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);363KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));364}365366/* Write the whole of PM in a single unpacked payload */367static void wmfw_write_all_unpacked_pm(struct kunit *test)368{369struct cs_dsp_test *priv = test->priv;370struct cs_dsp_test_local *local = priv->local;371struct firmware *wmfw;372unsigned int reg_addr;373u8 *payload_data, *readback;374unsigned int payload_size_bytes;375376payload_size_bytes = cs_dsp_mock_size_of_region(priv->dsp, WMFW_ADSP2_PM);377payload_data = vmalloc(payload_size_bytes);378KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);379kunit_add_action_or_reset(priv->test, _vfree_wrapper, payload_data);380381readback = vmalloc(payload_size_bytes);382KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);383kunit_add_action_or_reset(priv->test, _vfree_wrapper, readback);384memset(readback, 0, payload_size_bytes);385386/* Add a single PM payload */387get_random_bytes(payload_data, payload_size_bytes);388cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,389WMFW_ADSP2_PM, 0,390payload_data, payload_size_bytes);391392wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);393394KUNIT_EXPECT_EQ(test,395cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),3960);397398reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_PM);399KUNIT_EXPECT_EQ(test,400regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),4010);402KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);403404/* Drop expected writes and the cache should then be clean */405cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);406cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);407KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));408}409410/* Write the whole of PM in a single packed payload */411static void wmfw_write_all_packed_pm(struct kunit *test)412{413struct cs_dsp_test *priv = test->priv;414struct cs_dsp_test_local *local = priv->local;415struct firmware *wmfw;416unsigned int reg_addr;417u8 *payload_data, *readback;418unsigned int payload_size_bytes;419420payload_size_bytes = cs_dsp_mock_size_of_region(priv->dsp, WMFW_HALO_PM_PACKED);421payload_data = vmalloc(payload_size_bytes);422KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);423kunit_add_action_or_reset(priv->test, _vfree_wrapper, payload_data);424425readback = vmalloc(payload_size_bytes);426KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);427kunit_add_action_or_reset(priv->test, _vfree_wrapper, readback);428memset(readback, 0, payload_size_bytes);429430/* Add a single PM payload */431get_random_bytes(payload_data, payload_size_bytes);432cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,433WMFW_HALO_PM_PACKED, 0,434payload_data, payload_size_bytes);435436wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);437438KUNIT_EXPECT_EQ(test,439cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),4400);441442reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_PM_PACKED);443KUNIT_EXPECT_EQ(test,444regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),4450);446KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);447448/* Drop expected writes and the cache should then be clean */449cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);450cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);451KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));452}453454/*455* Write a series of payloads to various unpacked memory regions.456* The payloads are of various lengths and offsets, driven by the457* payload_defs table. The offset and length are both given as a458* number of minimum-sized register blocks to keep the maths simpler.459* (Where a minimum-sized register block is the smallest number of460* registers that contain a whole number of DSP words.)461*/462static void wmfw_write_multiple_unpacked_mem(struct kunit *test)463{464static const struct {465int mem_type;466unsigned int offset_num_blocks;467unsigned int num_blocks;468} payload_defs[] = {469{ WMFW_ADSP2_PM, 11, 60 },470{ WMFW_ADSP2_ZM, 69, 8 },471{ WMFW_ADSP2_YM, 32, 74 },472{ WMFW_ADSP2_XM, 70, 38 },473{ WMFW_ADSP2_PM, 84, 48 },474{ WMFW_ADSP2_XM, 46, 18 },475{ WMFW_ADSP2_PM, 0, 8 },476{ WMFW_ADSP2_YM, 0, 30 },477{ WMFW_ADSP2_PM, 160, 50 },478{ WMFW_ADSP2_ZM, 21, 26 },479};480struct cs_dsp_test *priv = test->priv;481struct cs_dsp_test_local *local = priv->local;482struct firmware *wmfw;483unsigned int payload_size_bytes, offset_num_dsp_words;484unsigned int reg_addr, offset_bytes, offset_num_regs;485void **payload_data;486void *readback;487int i, ret;488489payload_data = kunit_kcalloc(test, ARRAY_SIZE(payload_defs), sizeof(*payload_data),490GFP_KERNEL);491KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);492493for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {494payload_size_bytes = payload_defs[i].num_blocks *495cs_dsp_mock_reg_block_length_bytes(priv,496payload_defs[i].mem_type);497498payload_data[i] = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);499KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data[i]);500get_random_bytes(payload_data[i], payload_size_bytes);501502offset_num_dsp_words = payload_defs[i].offset_num_blocks *503cs_dsp_mock_reg_block_length_dsp_words(priv,504payload_defs[i].mem_type);505cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,506payload_defs[i].mem_type,507offset_num_dsp_words,508payload_data[i],509payload_size_bytes);510}511512wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);513514KUNIT_EXPECT_EQ(test,515cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),5160);517518for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {519payload_size_bytes = payload_defs[i].num_blocks *520cs_dsp_mock_reg_block_length_bytes(priv,521payload_defs[i].mem_type);522523readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);524KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);525526offset_bytes = payload_defs[i].offset_num_blocks *527cs_dsp_mock_reg_block_length_bytes(priv, payload_defs[i].mem_type);528offset_num_regs = offset_bytes / regmap_get_val_bytes(priv->dsp->regmap);529reg_addr = cs_dsp_mock_base_addr_for_mem(priv, payload_defs[i].mem_type);530reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);531ret = regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes);532KUNIT_EXPECT_EQ_MSG(test, ret, 0, "%s @%u num:%u\n",533cs_dsp_mem_region_name(payload_defs[i].mem_type),534payload_defs[i].offset_num_blocks, payload_defs[i].num_blocks);535KUNIT_EXPECT_MEMEQ_MSG(test, readback, payload_data[i], payload_size_bytes,536"%s @%u num:%u\n",537cs_dsp_mem_region_name(payload_defs[i].mem_type),538payload_defs[i].offset_num_blocks,539payload_defs[i].num_blocks);540541kunit_kfree(test, readback);542543cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);544}545546/* Drop expected writes and the cache should then be clean */547cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);548KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));549}550551/*552* Write a series of payloads to various packed and unpacked memory regions.553* The payloads are of various lengths and offsets, driven by the554* payload_defs table. The offset and length are both given as a555* number of minimum-sized register blocks to keep the maths simpler.556* (Where a minimum-sized register block is the smallest number of557* registers that contain a whole number of DSP words.)558*/559static void wmfw_write_multiple_packed_unpacked_mem(struct kunit *test)560{561static const struct {562int mem_type;563unsigned int offset_num_blocks;564unsigned int num_blocks;565} payload_defs[] = {566{ WMFW_HALO_PM_PACKED, 11, 60 },567{ WMFW_ADSP2_YM, 69, 8 },568{ WMFW_HALO_YM_PACKED, 32, 74 },569{ WMFW_HALO_XM_PACKED, 70, 38 },570{ WMFW_HALO_PM_PACKED, 84, 48 },571{ WMFW_HALO_XM_PACKED, 46, 18 },572{ WMFW_HALO_PM_PACKED, 0, 8 },573{ WMFW_HALO_YM_PACKED, 0, 30 },574{ WMFW_HALO_PM_PACKED, 160, 50 },575{ WMFW_ADSP2_XM, 21, 26 },576};577struct cs_dsp_test *priv = test->priv;578struct cs_dsp_test_local *local = priv->local;579struct firmware *wmfw;580unsigned int payload_size_bytes, offset_num_dsp_words;581unsigned int reg_addr, offset_bytes, offset_num_regs;582void **payload_data;583void *readback;584int i, ret;585586payload_data = kunit_kcalloc(test, ARRAY_SIZE(payload_defs), sizeof(*payload_data),587GFP_KERNEL);588KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);589590for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {591payload_size_bytes = payload_defs[i].num_blocks *592cs_dsp_mock_reg_block_length_bytes(priv,593payload_defs[i].mem_type);594595payload_data[i] = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);596KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data[i]);597get_random_bytes(payload_data[i], payload_size_bytes);598599offset_num_dsp_words = payload_defs[i].offset_num_blocks *600cs_dsp_mock_reg_block_length_dsp_words(priv,601payload_defs[i].mem_type);602cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,603payload_defs[i].mem_type,604offset_num_dsp_words,605payload_data[i],606payload_size_bytes);607}608609wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);610611KUNIT_EXPECT_EQ(test,612cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),6130);614615for (i = 0; i < ARRAY_SIZE(payload_defs); ++i) {616payload_size_bytes = payload_defs[i].num_blocks *617cs_dsp_mock_reg_block_length_bytes(priv,618payload_defs[i].mem_type);619620readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);621KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);622623offset_bytes = payload_defs[i].offset_num_blocks *624cs_dsp_mock_reg_block_length_bytes(priv, payload_defs[i].mem_type);625offset_num_regs = offset_bytes / regmap_get_val_bytes(priv->dsp->regmap);626reg_addr = cs_dsp_mock_base_addr_for_mem(priv, payload_defs[i].mem_type);627reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);628ret = regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes);629KUNIT_EXPECT_EQ_MSG(test, ret, 0, "%s @%u num:%u\n",630cs_dsp_mem_region_name(payload_defs[i].mem_type),631payload_defs[i].offset_num_blocks,632payload_defs[i].num_blocks);633KUNIT_EXPECT_MEMEQ_MSG(test, readback, payload_data[i], payload_size_bytes,634"%s @%u num:%u\n",635cs_dsp_mem_region_name(payload_defs[i].mem_type),636payload_defs[i].offset_num_blocks,637payload_defs[i].num_blocks);638639kunit_kfree(test, readback);640641cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, payload_size_bytes);642}643644/* Drop expected writes and the cache should then be clean */645cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);646KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));647}648649/*650* Write XM/YM data that is one word longer than a packed block multiple,651* using one packed payload followed by one unpacked word.652*/653static void wmfw_write_packed_1_unpacked_trailing(struct kunit *test)654{655const struct cs_dsp_wmfw_test_param *param = test->param_value;656struct cs_dsp_test *priv = test->priv;657struct cs_dsp_test_local *local = priv->local;658int packed_mem_type = param->mem_type;659int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);660unsigned int dsp_words_per_packed_block =661cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);662unsigned int dsp_words_per_unpacked_block =663cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);664unsigned int mem_offset_dsp_words = 0;665struct firmware *wmfw;666unsigned int reg_addr;667void *packed_payload_data, *readback;668u32 unpacked_payload_data[1];669unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;670unsigned int offset_num_regs;671672packed_payload_size_bytes = param->num_blocks *673cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);674packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;675676packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);677KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);678get_random_bytes(packed_payload_data, packed_payload_size_bytes);679680get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));681682readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);683684/* Tests on XM must be after the XM header */685if (unpacked_mem_type == WMFW_ADSP2_XM) {686mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);687688/* Round up to multiple of packed block length */689mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);690}691692/* Add a single packed payload */693cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,694packed_mem_type, mem_offset_dsp_words,695packed_payload_data, packed_payload_size_bytes);696/*697* Add payload of one unpacked word to DSP memory right after698* the packed payload words.699*/700cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,701unpacked_mem_type,702mem_offset_dsp_words + packed_payload_size_dsp_words,703unpacked_payload_data, sizeof(unpacked_payload_data));704705/* Download the wmfw */706wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);707KUNIT_EXPECT_EQ(test,708cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),7090);710711/*712* Check that the packed payload was written correctly and drop713* it from the regmap cache.714*/715offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *716cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);717reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);718reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);719KUNIT_EXPECT_EQ(test,720regmap_raw_read(priv->dsp->regmap, reg_addr, readback,721packed_payload_size_bytes),7220);723KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);724725cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);726727/*728* Check that the unpacked word was written correctly and drop729* it from the regmap cache. The unpacked payload is offset within730* unpacked register space by the number of DSP words that were731* written in the packed payload.732*/733offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *734cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);735offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *736cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);737reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);738reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);739KUNIT_EXPECT_EQ(test,740regmap_raw_read(priv->dsp->regmap, reg_addr, readback,741sizeof(unpacked_payload_data)),7420);743KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));744745cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));746747/* Drop expected writes and the cache should then be clean */748cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);749KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));750}751752/*753* Write XM/YM data that is two words longer than a packed block multiple,754* using one packed payload followed by one payload of two unpacked words.755*/756static void wmfw_write_packed_2_unpacked_trailing(struct kunit *test)757{758const struct cs_dsp_wmfw_test_param *param = test->param_value;759struct cs_dsp_test *priv = test->priv;760struct cs_dsp_test_local *local = priv->local;761int packed_mem_type = param->mem_type;762int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);763unsigned int dsp_words_per_packed_block =764cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);765unsigned int dsp_words_per_unpacked_block =766cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);767unsigned int mem_offset_dsp_words = 0;768struct firmware *wmfw;769unsigned int reg_addr;770void *packed_payload_data, *readback;771u32 unpacked_payload_data[2];772unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;773unsigned int offset_num_regs;774775packed_payload_size_bytes = param->num_blocks *776cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);777packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;778779packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);780KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);781get_random_bytes(packed_payload_data, packed_payload_size_bytes);782783get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));784785readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);786787/* Tests on XM must be after the XM header */788if (unpacked_mem_type == WMFW_ADSP2_XM) {789mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);790791/* Round up to multiple of packed block length */792mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);793}794795/* Add a single packed payload */796cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,797packed_mem_type, mem_offset_dsp_words,798packed_payload_data, packed_payload_size_bytes);799/*800* Add payload of two unpacked words to DSP memory right after801* the packed payload words.802*/803cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,804unpacked_mem_type,805mem_offset_dsp_words + packed_payload_size_dsp_words,806unpacked_payload_data, sizeof(unpacked_payload_data));807808/* Download the wmfw */809wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);810KUNIT_EXPECT_EQ(test,811cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),8120);813814/*815* Check that the packed payload was written correctly and drop816* it from the regmap cache.817*/818offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *819cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);820reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);821reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);822KUNIT_EXPECT_EQ(test,823regmap_raw_read(priv->dsp->regmap, reg_addr, readback,824packed_payload_size_bytes),8250);826KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);827828cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);829830/*831* Check that the unpacked words were written correctly and drop832* them from the regmap cache. The unpacked payload is offset833* within unpacked register space by the number of DSP words834* that were written in the packed payload.835*/836offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *837cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);838offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *839cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);840reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);841reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);842KUNIT_EXPECT_EQ(test,843regmap_raw_read(priv->dsp->regmap, reg_addr, readback,844sizeof(unpacked_payload_data)),8450);846KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));847848cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));849850/* Drop expected writes and the cache should then be clean */851cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);852KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));853}854855/*856* Write XM/YM data that is three words longer than a packed block multiple,857* using one packed payload followed by one payload of three unpacked words.858*/859static void wmfw_write_packed_3_unpacked_trailing(struct kunit *test)860{861const struct cs_dsp_wmfw_test_param *param = test->param_value;862struct cs_dsp_test *priv = test->priv;863struct cs_dsp_test_local *local = priv->local;864int packed_mem_type = param->mem_type;865int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);866unsigned int dsp_words_per_packed_block =867cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);868unsigned int dsp_words_per_unpacked_block =869cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);870unsigned int mem_offset_dsp_words = 0;871struct firmware *wmfw;872unsigned int reg_addr;873void *packed_payload_data, *readback;874u32 unpacked_payload_data[3];875unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;876unsigned int offset_num_regs;877878packed_payload_size_bytes = param->num_blocks *879cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);880packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;881882packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);883KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);884get_random_bytes(packed_payload_data, packed_payload_size_bytes);885886get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));887888readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);889890/* Tests on XM must be after the XM header */891if (unpacked_mem_type == WMFW_ADSP2_XM) {892mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);893894/* Round up to multiple of packed block length */895mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);896}897898/* Add a single packed payload */899cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,900packed_mem_type, mem_offset_dsp_words,901packed_payload_data, packed_payload_size_bytes);902/*903* Add payload of three unpacked words to DSP memory right after904* the packed payload words.905*/906cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,907unpacked_mem_type,908mem_offset_dsp_words + packed_payload_size_dsp_words,909unpacked_payload_data, sizeof(unpacked_payload_data));910911/* Download the wmfw */912wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);913KUNIT_EXPECT_EQ(test,914cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),9150);916917/*918* Check that the packed payload was written correctly and drop919* it from the regmap cache.920*/921offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *922cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);923reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);924reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);925KUNIT_EXPECT_EQ(test,926regmap_raw_read(priv->dsp->regmap, reg_addr, readback,927packed_payload_size_bytes),9280);929KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);930931cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);932933/*934* Check that the unpacked words were written correctly and drop935* them from the regmap cache. The unpacked payload is offset936* within unpacked register space by the number of DSP words937* that were written in the packed payload.938*/939offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *940cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);941offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *942cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);943reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);944reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);945KUNIT_EXPECT_EQ(test,946regmap_raw_read(priv->dsp->regmap, reg_addr, readback,947sizeof(unpacked_payload_data)),9480);949KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));950951cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));952953/* Drop expected writes and the cache should then be clean */954cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);955KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));956}957958/*959* Write XM/YM data that is two words longer than a packed block multiple,960* using one packed payload followed by two payloads of one unpacked word each.961*/962static void wmfw_write_packed_2_single_unpacked_trailing(struct kunit *test)963{964const struct cs_dsp_wmfw_test_param *param = test->param_value;965struct cs_dsp_test *priv = test->priv;966struct cs_dsp_test_local *local = priv->local;967int packed_mem_type = param->mem_type;968int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);969unsigned int dsp_words_per_packed_block =970cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);971unsigned int dsp_words_per_unpacked_block =972cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);973unsigned int mem_offset_dsp_words = 0;974struct firmware *wmfw;975unsigned int reg_addr;976void *packed_payload_data, *readback;977u32 unpacked_payload_data[2];978unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;979unsigned int offset_num_regs;980981packed_payload_size_bytes = param->num_blocks *982cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);983packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;984985packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);986KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);987get_random_bytes(packed_payload_data, packed_payload_size_bytes);988989get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));990991readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);992993/* Tests on XM must be after the XM header */994if (unpacked_mem_type == WMFW_ADSP2_XM) {995mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);996997/* Round up to multiple of packed block length */998mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);999}10001001/* Add a single packed payload */1002cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1003packed_mem_type, mem_offset_dsp_words,1004packed_payload_data, packed_payload_size_bytes);1005/*1006* Add two unpacked words to DSP memory right after the packed1007* payload words. Each unpacked word in its own payload.1008*/1009cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1010unpacked_mem_type,1011mem_offset_dsp_words + packed_payload_size_dsp_words,1012&unpacked_payload_data[0],1013sizeof(unpacked_payload_data[0]));1014cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1015unpacked_mem_type,1016mem_offset_dsp_words + packed_payload_size_dsp_words + 1,1017&unpacked_payload_data[1],1018sizeof(unpacked_payload_data[1]));10191020/* Download the wmfw */1021wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1022KUNIT_EXPECT_EQ(test,1023cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),10240);10251026/*1027* Check that the packed payload was written correctly and drop1028* it from the regmap cache.1029*/1030offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *1031cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1032reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1033reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1034KUNIT_EXPECT_EQ(test,1035regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1036packed_payload_size_bytes),10370);1038KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);10391040cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);10411042/*1043* Check that the unpacked words were written correctly and drop1044* them from the regmap cache. The unpacked words are offset1045* within unpacked register space by the number of DSP words1046* that were written in the packed payload.1047*/1048offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *1049cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1050offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *1051cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1052reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1053reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1054KUNIT_EXPECT_EQ(test,1055regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1056sizeof(unpacked_payload_data)),10570);1058KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));10591060cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));10611062/* Drop expected writes and the cache should then be clean */1063cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1064KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1065}10661067/*1068* Write XM/YM data that is three words longer than a packed block multiple,1069* using one packed payload followed by three payloads of one unpacked word each.1070*/1071static void wmfw_write_packed_3_single_unpacked_trailing(struct kunit *test)1072{1073const struct cs_dsp_wmfw_test_param *param = test->param_value;1074struct cs_dsp_test *priv = test->priv;1075struct cs_dsp_test_local *local = priv->local;1076int packed_mem_type = param->mem_type;1077int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1078unsigned int dsp_words_per_packed_block =1079cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);1080unsigned int dsp_words_per_unpacked_block =1081cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);1082unsigned int mem_offset_dsp_words = 0;1083struct firmware *wmfw;1084unsigned int reg_addr;1085void *packed_payload_data, *readback;1086u32 unpacked_payload_data[3];1087unsigned int packed_payload_size_bytes, packed_payload_size_dsp_words;1088unsigned int offset_num_regs;10891090packed_payload_size_bytes = param->num_blocks *1091cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);1092packed_payload_size_dsp_words = param->num_blocks * dsp_words_per_packed_block;10931094packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);1095KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);1096get_random_bytes(packed_payload_data, packed_payload_size_bytes);10971098get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));10991100readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);11011102/* Tests on XM must be after the XM header */1103if (unpacked_mem_type == WMFW_ADSP2_XM) {1104mem_offset_dsp_words += local->xm_header->blob_size_bytes / sizeof(u32);11051106/* Round up to multiple of packed block length */1107mem_offset_dsp_words = roundup(mem_offset_dsp_words, dsp_words_per_packed_block);1108}11091110/* Add a single packed payload */1111cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1112packed_mem_type, mem_offset_dsp_words,1113packed_payload_data, packed_payload_size_bytes);1114/*1115* Add three unpacked words to DSP memory right after the packed1116* payload words. Each unpacked word in its own payload.1117*/1118cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1119unpacked_mem_type,1120mem_offset_dsp_words + packed_payload_size_dsp_words,1121&unpacked_payload_data[0],1122sizeof(unpacked_payload_data[0]));1123cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1124unpacked_mem_type,1125mem_offset_dsp_words + packed_payload_size_dsp_words + 1,1126&unpacked_payload_data[1],1127sizeof(unpacked_payload_data[1]));1128cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1129unpacked_mem_type,1130mem_offset_dsp_words + packed_payload_size_dsp_words + 2,1131&unpacked_payload_data[2],1132sizeof(unpacked_payload_data[2]));11331134/* Download the wmfw */1135wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1136KUNIT_EXPECT_EQ(test,1137cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),11380);1139/*1140* Check that the packed payload was written correctly and drop1141* it from the regmap cache.1142*/1143offset_num_regs = (mem_offset_dsp_words / dsp_words_per_packed_block) *1144cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1145reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1146reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1147KUNIT_EXPECT_EQ(test,1148regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1149packed_payload_size_bytes),11500);1151KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);11521153cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);11541155/*1156* Check that the unpacked words were written correctly and drop1157* them from the regmap cache. The unpacked words are offset1158* within unpacked register space by the number of DSP words1159* that were written in the packed payload.1160*/1161offset_num_regs = (mem_offset_dsp_words / dsp_words_per_unpacked_block) *1162cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1163offset_num_regs += (packed_payload_size_dsp_words / dsp_words_per_unpacked_block) *1164cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1165reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1166reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1167KUNIT_EXPECT_EQ(test,1168regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1169sizeof(unpacked_payload_data)),11700);1171KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));11721173cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));11741175/* Drop expected writes and the cache should then be clean */1176cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1177KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1178}11791180/*1181* Write XM/YM data that is one word longer than a packed block multiple,1182* and does not start on a packed alignment. Use one unpacked word1183* followed by a packed payload.1184*/1185static void wmfw_write_packed_1_unpacked_leading(struct kunit *test)1186{1187const struct cs_dsp_wmfw_test_param *param = test->param_value;1188struct cs_dsp_test *priv = test->priv;1189struct cs_dsp_test_local *local = priv->local;1190int packed_mem_type = param->mem_type;1191int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1192unsigned int dsp_words_per_packed_block =1193cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);1194unsigned int dsp_words_per_unpacked_block =1195cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);1196unsigned int packed_payload_offset_dsp_words = 0;1197struct firmware *wmfw;1198unsigned int reg_addr;1199void *packed_payload_data, *readback;1200u32 unpacked_payload_data[1];1201unsigned int packed_payload_size_bytes;1202unsigned int offset_num_regs;12031204packed_payload_size_bytes = param->num_blocks *1205cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);12061207packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);1208KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);1209get_random_bytes(packed_payload_data, packed_payload_size_bytes);12101211get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));12121213readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);12141215/* Tests on XM must be after the XM header */1216if (unpacked_mem_type == WMFW_ADSP2_XM)1217packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /1218sizeof(u32);1219/*1220* Leave space for an unaligned word before the packed block and1221* round the packed block start to multiple of packed block length.1222*/1223packed_payload_offset_dsp_words += 1;1224packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,1225dsp_words_per_packed_block);12261227/* Add a single unpacked word right before the first word of packed data */1228cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1229unpacked_mem_type,1230packed_payload_offset_dsp_words - 1,1231unpacked_payload_data, sizeof(unpacked_payload_data));12321233/* Add payload of packed data to the DSP memory after the unpacked word. */1234cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1235packed_mem_type,1236packed_payload_offset_dsp_words,1237packed_payload_data, packed_payload_size_bytes);12381239/* Download the wmfw */1240wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1241KUNIT_EXPECT_EQ(test,1242cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),12430);1244/*1245* Check that the packed payload was written correctly and drop1246* it from the regmap cache.1247*/1248offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *1249cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1250reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1251reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1252KUNIT_EXPECT_EQ(test,1253regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1254packed_payload_size_bytes),12550);1256KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);12571258cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);12591260/*1261* Check that the unpacked word was written correctly and drop1262* it from the regmap cache.1263*/1264offset_num_regs = ((packed_payload_offset_dsp_words - 1) / dsp_words_per_unpacked_block) *1265cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1266reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1267reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1268KUNIT_EXPECT_EQ(test,1269regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1270sizeof(unpacked_payload_data)),12710);1272KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));12731274cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));12751276/* Drop expected writes and the cache should then be clean */1277cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1278KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1279}12801281/*1282* Write XM/YM data that is two words longer than a packed block multiple,1283* and does not start on a packed alignment. Use one payload of two unpacked1284* words followed by a packed payload.1285*/1286static void wmfw_write_packed_2_unpacked_leading(struct kunit *test)1287{1288const struct cs_dsp_wmfw_test_param *param = test->param_value;1289struct cs_dsp_test *priv = test->priv;1290struct cs_dsp_test_local *local = priv->local;1291int packed_mem_type = param->mem_type;1292int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1293unsigned int dsp_words_per_packed_block =1294cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);1295unsigned int dsp_words_per_unpacked_block =1296cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);1297unsigned int packed_payload_offset_dsp_words = 0;1298struct firmware *wmfw;1299unsigned int reg_addr;1300void *packed_payload_data, *readback;1301u32 unpacked_payload_data[2];1302unsigned int packed_payload_size_bytes;1303unsigned int offset_num_regs;13041305packed_payload_size_bytes = param->num_blocks *1306cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);13071308packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);1309KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);1310get_random_bytes(packed_payload_data, packed_payload_size_bytes);13111312get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));13131314readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);13151316/* Tests on XM must be after the XM header */1317if (unpacked_mem_type == WMFW_ADSP2_XM)1318packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /1319sizeof(u32);1320/*1321* Leave space for two unaligned words before the packed block and1322* round the packed block start to multiple of packed block length.1323*/1324packed_payload_offset_dsp_words += 2;1325packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,1326dsp_words_per_packed_block);13271328/*1329* Add two unpacked words as a single payload right before the1330* first word of packed data1331*/1332cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1333unpacked_mem_type,1334packed_payload_offset_dsp_words - 2,1335unpacked_payload_data, sizeof(unpacked_payload_data));13361337/* Add payload of packed data to the DSP memory after the unpacked words. */1338cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1339packed_mem_type,1340packed_payload_offset_dsp_words,1341packed_payload_data, packed_payload_size_bytes);13421343/* Download the wmfw */1344wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1345KUNIT_EXPECT_EQ(test,1346cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),13470);1348/*1349* Check that the packed payload was written correctly and drop1350* it from the regmap cache.1351*/1352offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *1353cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1354reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1355reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1356KUNIT_EXPECT_EQ(test,1357regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1358packed_payload_size_bytes),13590);1360KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);13611362cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);13631364/*1365* Check that the unpacked words were written correctly and drop1366* them from the regmap cache.1367*/1368offset_num_regs = ((packed_payload_offset_dsp_words - 2) / dsp_words_per_unpacked_block) *1369cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1370reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1371reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1372KUNIT_EXPECT_EQ(test,1373regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1374sizeof(unpacked_payload_data)),13750);1376KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));13771378cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));13791380/* Drop expected writes and the cache should then be clean */1381cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1382KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1383}13841385/*1386* Write XM/YM data that is three words longer than a packed block multiple,1387* and does not start on a packed alignment. Use one payload of three unpacked1388* words followed by a packed payload.1389*/1390static void wmfw_write_packed_3_unpacked_leading(struct kunit *test)1391{1392const struct cs_dsp_wmfw_test_param *param = test->param_value;1393struct cs_dsp_test *priv = test->priv;1394struct cs_dsp_test_local *local = priv->local;1395int packed_mem_type = param->mem_type;1396int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1397unsigned int dsp_words_per_packed_block =1398cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);1399unsigned int dsp_words_per_unpacked_block =1400cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);1401unsigned int packed_payload_offset_dsp_words = 0;1402struct firmware *wmfw;1403unsigned int reg_addr;1404void *packed_payload_data, *readback;1405u32 unpacked_payload_data[3];1406unsigned int packed_payload_size_bytes;1407unsigned int offset_num_regs;14081409packed_payload_size_bytes = param->num_blocks *1410cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);14111412packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);1413KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);1414get_random_bytes(packed_payload_data, packed_payload_size_bytes);14151416get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));14171418readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);14191420/* Tests on XM must be after the XM header */1421if (unpacked_mem_type == WMFW_ADSP2_XM)1422packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /1423sizeof(u32);1424/*1425* Leave space for three unaligned words before the packed block and1426* round the packed block start to multiple of packed block length.1427*/1428packed_payload_offset_dsp_words += 3;1429packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,1430dsp_words_per_packed_block);14311432/*1433* Add three unpacked words as a single payload right before the1434* first word of packed data1435*/1436cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1437unpacked_mem_type,1438packed_payload_offset_dsp_words - 3,1439unpacked_payload_data, sizeof(unpacked_payload_data));14401441/* Add payload of packed data to the DSP memory after the unpacked words. */1442cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1443packed_mem_type,1444packed_payload_offset_dsp_words,1445packed_payload_data, packed_payload_size_bytes);14461447/* Download the wmfw */1448wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1449KUNIT_EXPECT_EQ(test,1450cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),14510);1452/*1453* Check that the packed payload was written correctly and drop1454* it from the regmap cache.1455*/1456offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *1457cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1458reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1459reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1460KUNIT_EXPECT_EQ(test,1461regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1462packed_payload_size_bytes),14630);1464KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);14651466cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);14671468/*1469* Check that the unpacked words were written correctly and drop1470* them from the regmap cache.1471*/1472offset_num_regs = ((packed_payload_offset_dsp_words - 3) / dsp_words_per_unpacked_block) *1473cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1474reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1475reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1476KUNIT_EXPECT_EQ(test,1477regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1478sizeof(unpacked_payload_data)),14790);1480KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));14811482cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));14831484/* Drop expected writes and the cache should then be clean */1485cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1486KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1487}14881489/*1490* Write XM/YM data that is two words longer than a packed block multiple,1491* and does not start on a packed alignment. Use two payloads of one unpacked1492* word each, followed by a packed payload.1493*/1494static void wmfw_write_packed_2_single_unpacked_leading(struct kunit *test)1495{1496const struct cs_dsp_wmfw_test_param *param = test->param_value;1497struct cs_dsp_test *priv = test->priv;1498struct cs_dsp_test_local *local = priv->local;1499int packed_mem_type = param->mem_type;1500int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1501unsigned int dsp_words_per_packed_block =1502cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);1503unsigned int dsp_words_per_unpacked_block =1504cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);1505unsigned int packed_payload_offset_dsp_words = 0;1506struct firmware *wmfw;1507unsigned int reg_addr;1508void *packed_payload_data, *readback;1509u32 unpacked_payload_data[2];1510unsigned int packed_payload_size_bytes;1511unsigned int offset_num_regs;15121513packed_payload_size_bytes = param->num_blocks *1514cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);15151516packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);1517KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);1518get_random_bytes(packed_payload_data, packed_payload_size_bytes);15191520get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));15211522readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);15231524/* Tests on XM must be after the XM header */1525if (unpacked_mem_type == WMFW_ADSP2_XM)1526packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /1527sizeof(u32);1528/*1529* Leave space for two unaligned words before the packed block and1530* round the packed block start to multiple of packed block length.1531*/1532packed_payload_offset_dsp_words += 2;1533packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,1534dsp_words_per_packed_block);15351536/*1537* Add two unpacked words as two payloads each containing a single1538* unpacked word.1539*/1540cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1541unpacked_mem_type,1542packed_payload_offset_dsp_words - 2,1543&unpacked_payload_data[0],1544sizeof(unpacked_payload_data[0]));1545cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1546unpacked_mem_type,1547packed_payload_offset_dsp_words - 1,1548&unpacked_payload_data[1],1549sizeof(unpacked_payload_data[1]));15501551/* Add payload of packed data to the DSP memory after the unpacked words. */1552cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1553packed_mem_type,1554packed_payload_offset_dsp_words,1555packed_payload_data, packed_payload_size_bytes);15561557/* Download the wmfw */1558wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1559KUNIT_EXPECT_EQ(test,1560cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),15610);1562/*1563* Check that the packed payload was written correctly and drop1564* it from the regmap cache.1565*/1566offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *1567cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1568reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1569reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1570KUNIT_EXPECT_EQ(test,1571regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1572packed_payload_size_bytes),15730);1574KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);15751576cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);15771578/*1579* Check that the unpacked words were written correctly and drop1580* them from the regmap cache.1581*/1582offset_num_regs = ((packed_payload_offset_dsp_words - 2) / dsp_words_per_unpacked_block) *1583cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1584reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1585reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1586KUNIT_EXPECT_EQ(test,1587regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1588sizeof(unpacked_payload_data)),15890);1590KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));15911592cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));15931594/* Drop expected writes and the cache should then be clean */1595cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1596KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1597}15981599/*1600* Write XM/YM data that is three words longer than a packed block multiple,1601* and does not start on a packed alignment. Use three payloads of one unpacked1602* word each, followed by a packed payload.1603*/1604static void wmfw_write_packed_3_single_unpacked_leading(struct kunit *test)1605{1606const struct cs_dsp_wmfw_test_param *param = test->param_value;1607struct cs_dsp_test *priv = test->priv;1608struct cs_dsp_test_local *local = priv->local;1609int packed_mem_type = param->mem_type;1610int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1611unsigned int dsp_words_per_packed_block =1612cs_dsp_mock_reg_block_length_dsp_words(priv, packed_mem_type);1613unsigned int dsp_words_per_unpacked_block =1614cs_dsp_mock_reg_block_length_dsp_words(priv, unpacked_mem_type);1615unsigned int packed_payload_offset_dsp_words = 0;1616struct firmware *wmfw;1617unsigned int reg_addr;1618void *packed_payload_data, *readback;1619u32 unpacked_payload_data[3];1620unsigned int packed_payload_size_bytes;1621unsigned int offset_num_regs;16221623packed_payload_size_bytes = param->num_blocks *1624cs_dsp_mock_reg_block_length_bytes(priv, packed_mem_type);16251626packed_payload_data = kunit_kmalloc(test, packed_payload_size_bytes, GFP_KERNEL);1627KUNIT_ASSERT_NOT_ERR_OR_NULL(test, packed_payload_data);1628get_random_bytes(packed_payload_data, packed_payload_size_bytes);16291630get_random_bytes(unpacked_payload_data, sizeof(unpacked_payload_data));16311632readback = kunit_kzalloc(test, packed_payload_size_bytes, GFP_KERNEL);16331634/* Tests on XM must be after the XM header */1635if (unpacked_mem_type == WMFW_ADSP2_XM)1636packed_payload_offset_dsp_words += local->xm_header->blob_size_bytes /1637sizeof(u32);1638/*1639* Leave space for two unaligned words before the packed block and1640* round the packed block start to multiple of packed block length.1641*/1642packed_payload_offset_dsp_words += 3;1643packed_payload_offset_dsp_words = roundup(packed_payload_offset_dsp_words,1644dsp_words_per_packed_block);16451646/*1647* Add three unpacked words as three payloads each containing a single1648* unpacked word.1649*/1650cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1651unpacked_mem_type,1652packed_payload_offset_dsp_words - 3,1653&unpacked_payload_data[0],1654sizeof(unpacked_payload_data[0]));1655cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1656unpacked_mem_type,1657packed_payload_offset_dsp_words - 2,1658&unpacked_payload_data[1],1659sizeof(unpacked_payload_data[1]));1660cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1661unpacked_mem_type,1662packed_payload_offset_dsp_words - 1,1663&unpacked_payload_data[2],1664sizeof(unpacked_payload_data[2]));16651666/* Add payload of packed data to the DSP memory after the unpacked words. */1667cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1668packed_mem_type,1669packed_payload_offset_dsp_words,1670packed_payload_data, packed_payload_size_bytes);16711672/* Download the wmfw */1673wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);1674KUNIT_EXPECT_EQ(test,1675cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc"),16760);1677/*1678* Check that the packed payload was written correctly and drop1679* it from the regmap cache.1680*/1681offset_num_regs = (packed_payload_offset_dsp_words / dsp_words_per_packed_block) *1682cs_dsp_mock_reg_block_length_registers(priv, packed_mem_type);1683reg_addr = cs_dsp_mock_base_addr_for_mem(priv, packed_mem_type);1684reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1685KUNIT_EXPECT_EQ(test,1686regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1687packed_payload_size_bytes),16880);1689KUNIT_EXPECT_MEMEQ(test, readback, packed_payload_data, packed_payload_size_bytes);16901691cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, packed_payload_size_bytes);16921693/*1694* Check that the unpacked words were written correctly and drop1695* them from the regmap cache.1696*/1697offset_num_regs = ((packed_payload_offset_dsp_words - 3) / dsp_words_per_unpacked_block) *1698cs_dsp_mock_reg_block_length_registers(priv, unpacked_mem_type);1699reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type);1700reg_addr += offset_num_regs * regmap_get_reg_stride(priv->dsp->regmap);1701KUNIT_EXPECT_EQ(test,1702regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1703sizeof(unpacked_payload_data)),17040);1705KUNIT_EXPECT_MEMEQ(test, readback, unpacked_payload_data, sizeof(unpacked_payload_data));17061707cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload_data));17081709/* Drop expected writes and the cache should then be clean */1710cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1711KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1712}17131714/* Load a wmfw containing multiple info blocks */1715static void wmfw_load_with_info(struct kunit *test)1716{1717struct cs_dsp_test *priv = test->priv;1718struct cs_dsp_test_local *local = priv->local;1719struct firmware *wmfw;1720unsigned int reg_addr;1721u8 *payload_data, *readback;1722char *infobuf;1723const unsigned int payload_size_bytes = 48;1724int ret;17251726payload_data = kunit_kmalloc(test, payload_size_bytes, GFP_KERNEL);1727KUNIT_ASSERT_NOT_ERR_OR_NULL(test, payload_data);1728get_random_bytes(payload_data, payload_size_bytes);17291730readback = kunit_kzalloc(test, payload_size_bytes, GFP_KERNEL);1731KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);17321733/* Add a couple of info blocks at the start of the wmfw */1734cs_dsp_mock_wmfw_add_info(local->wmfw_builder, "This is a timestamp");1735cs_dsp_mock_wmfw_add_info(local->wmfw_builder, "This is some more info");17361737/* Add a single payload */1738cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1739WMFW_ADSP2_YM, 0,1740payload_data, payload_size_bytes);17411742/* Add a bigger info block then another small one*/1743infobuf = kunit_kzalloc(test, 512, GFP_KERNEL);1744KUNIT_ASSERT_NOT_ERR_OR_NULL(test, infobuf);17451746for (; strlcat(infobuf, "Waffle{Blah}\n", 512) < 512;)1747;17481749cs_dsp_mock_wmfw_add_info(local->wmfw_builder, infobuf);1750cs_dsp_mock_wmfw_add_info(local->wmfw_builder, "Another block of info");17511752/* Add another payload */1753cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1754WMFW_ADSP2_YM, 64,1755payload_data, payload_size_bytes);17561757wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);17581759ret = cs_dsp_power_up(priv->dsp, wmfw, "mock_wmfw", NULL, NULL, "misc");1760KUNIT_EXPECT_EQ_MSG(test, ret, 0, "cs_dsp_power_up failed: %d\n", ret);17611762/* Check first payload was written */1763reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);1764KUNIT_EXPECT_EQ(test,1765regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),17660);1767KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);17681769/* Check second payload was written */1770reg_addr += cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv) * 64;1771KUNIT_EXPECT_EQ(test,1772regmap_raw_read(priv->dsp->regmap, reg_addr, readback, payload_size_bytes),17730);1774KUNIT_EXPECT_MEMEQ(test, readback, payload_data, payload_size_bytes);1775}17761777static int cs_dsp_wmfw_test_common_init(struct kunit *test, struct cs_dsp *dsp,1778int wmfw_version)1779{1780struct cs_dsp_test *priv;1781struct cs_dsp_test_local *local;1782struct device *test_dev;1783int ret;17841785priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);1786if (!priv)1787return -ENOMEM;17881789local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);1790if (!local)1791return -ENOMEM;17921793priv->test = test;1794priv->dsp = dsp;1795test->priv = priv;1796priv->local = local;1797priv->local->wmfw_version = wmfw_version;17981799/* Create dummy struct device */1800test_dev = kunit_device_register(test, "cs_dsp_test_drv");1801if (IS_ERR(test_dev))1802return PTR_ERR(test_dev);18031804dsp->dev = get_device(test_dev);1805if (!dsp->dev)1806return -ENODEV;18071808ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);1809if (ret)1810return ret;18111812dev_set_drvdata(dsp->dev, priv);18131814/* Allocate regmap */1815ret = cs_dsp_mock_regmap_init(priv);1816if (ret)1817return ret;18181819/*1820* There must always be a XM header with at least 1 algorithm, so create1821* a dummy one that tests can use and extract it to a data payload.1822*/1823local->xm_header = cs_dsp_create_mock_xm_header(priv,1824cs_dsp_wmfw_test_mock_algs,1825ARRAY_SIZE(cs_dsp_wmfw_test_mock_algs));1826KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);18271828local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, priv->local->wmfw_version);1829KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder);18301831/* Add dummy XM header payload to wmfw */1832cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,1833WMFW_ADSP2_XM, 0,1834local->xm_header->blob_data,1835local->xm_header->blob_size_bytes);18361837/* Init cs_dsp */1838dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);1839KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);18401841switch (dsp->type) {1842case WMFW_ADSP2:1843ret = cs_dsp_adsp2_init(dsp);1844break;1845case WMFW_HALO:1846ret = cs_dsp_halo_init(dsp);1847break;1848default:1849KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);1850return -EINVAL;1851}18521853if (ret)1854return ret;18551856/* Automatically call cs_dsp_remove() when test case ends */1857ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);1858if (ret)1859return ret;18601861/*1862* The large number of test cases will cause an unusually large amount1863* of dev_info() messages from cs_dsp, so suppress these.1864*/1865cs_dsp_suppress_info_messages = true;18661867return 0;1868}18691870static void cs_dsp_wmfw_test_exit(struct kunit *test)1871{1872cs_dsp_suppress_info_messages = false;1873}18741875static int cs_dsp_wmfw_test_halo_init(struct kunit *test)1876{1877struct cs_dsp *dsp;18781879/* Fill in cs_dsp and initialize */1880dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);1881if (!dsp)1882return -ENOMEM;18831884dsp->num = 1;1885dsp->type = WMFW_HALO;1886dsp->mem = cs_dsp_mock_halo_dsp1_regions;1887dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);1888dsp->base = cs_dsp_mock_halo_core_base;1889dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;18901891return cs_dsp_wmfw_test_common_init(test, dsp, 3);1892}18931894static int cs_dsp_wmfw_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)1895{1896struct cs_dsp *dsp;18971898/* Fill in cs_dsp and initialize */1899dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);1900if (!dsp)1901return -ENOMEM;19021903dsp->num = 1;1904dsp->type = WMFW_ADSP2;1905dsp->rev = 1;1906dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;1907dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);1908dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;19091910return cs_dsp_wmfw_test_common_init(test, dsp, wmfw_ver);1911}19121913static int cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init(struct kunit *test)1914{1915return cs_dsp_wmfw_test_adsp2_32bit_init(test, 0);1916}19171918static int cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init(struct kunit *test)1919{1920return cs_dsp_wmfw_test_adsp2_32bit_init(test, 1);1921}19221923static int cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init(struct kunit *test)1924{1925return cs_dsp_wmfw_test_adsp2_32bit_init(test, 2);1926}19271928static int cs_dsp_wmfw_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)1929{1930struct cs_dsp *dsp;19311932/* Fill in cs_dsp and initialize */1933dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);1934if (!dsp)1935return -ENOMEM;19361937dsp->num = 1;1938dsp->type = WMFW_ADSP2;1939dsp->rev = 0;1940dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;1941dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);1942dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;19431944return cs_dsp_wmfw_test_common_init(test, dsp, wmfw_ver);1945}19461947static int cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init(struct kunit *test)1948{1949return cs_dsp_wmfw_test_adsp2_16bit_init(test, 0);1950}19511952static int cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init(struct kunit *test)1953{1954return cs_dsp_wmfw_test_adsp2_16bit_init(test, 1);1955}19561957static int cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init(struct kunit *test)1958{1959return cs_dsp_wmfw_test_adsp2_16bit_init(test, 2);1960}19611962static void cs_dsp_mem_param_desc(const struct cs_dsp_wmfw_test_param *param, char *desc)1963{1964snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s num_blocks:%u",1965cs_dsp_mem_region_name(param->mem_type),1966param->num_blocks);1967}19681969static const struct cs_dsp_wmfw_test_param adsp2_all_num_blocks_param_cases[] = {1970{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 1 },1971{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 2 },1972{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 3 },1973{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 4 },1974{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 5 },1975{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 6 },1976{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 12 },1977{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 13 },1978{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 14 },1979{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 15 },1980{ .mem_type = WMFW_ADSP2_PM, .num_blocks = 16 },19811982{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 1 },1983{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 2 },1984{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 3 },1985{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 4 },1986{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 5 },1987{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 6 },1988{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 12 },1989{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 13 },1990{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 14 },1991{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 15 },1992{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 16 },19931994{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 1 },1995{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 2 },1996{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 3 },1997{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 4 },1998{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 5 },1999{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 6 },2000{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 12 },2001{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 13 },2002{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 14 },2003{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 15 },2004{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 16 },20052006{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 1 },2007{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 2 },2008{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 3 },2009{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 4 },2010{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 5 },2011{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 6 },2012{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 12 },2013{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 13 },2014{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 14 },2015{ .mem_type = WMFW_ADSP2_ZM, .num_blocks = 15 },2016{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 16 },2017};20182019KUNIT_ARRAY_PARAM(adsp2_all_num_blocks,2020adsp2_all_num_blocks_param_cases,2021cs_dsp_mem_param_desc);20222023static const struct cs_dsp_wmfw_test_param halo_all_num_blocks_param_cases[] = {2024{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 1 },2025{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 2 },2026{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 3 },2027{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 4 },2028{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 5 },2029{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 6 },2030{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 12 },2031{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 13 },2032{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 14 },2033{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 15 },2034{ .mem_type = WMFW_HALO_PM_PACKED, .num_blocks = 16 },20352036{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 1 },2037{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 2 },2038{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 3 },2039{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 4 },2040{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 5 },2041{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 6 },2042{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 12 },2043{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 13 },2044{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 14 },2045{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 15 },2046{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 16 },20472048{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 1 },2049{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 2 },2050{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 3 },2051{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 4 },2052{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 5 },2053{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 6 },2054{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 12 },2055{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 13 },2056{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 14 },2057{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 15 },2058{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 16 },20592060{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 1 },2061{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 2 },2062{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 3 },2063{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 4 },2064{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 5 },2065{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 6 },2066{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 12 },2067{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 13 },2068{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 14 },2069{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 15 },2070{ .mem_type = WMFW_ADSP2_XM, .num_blocks = 16 },20712072{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 1 },2073{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 2 },2074{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 3 },2075{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 4 },2076{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 5 },2077{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 6 },2078{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 12 },2079{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 13 },2080{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 14 },2081{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 15 },2082{ .mem_type = WMFW_ADSP2_YM, .num_blocks = 16 },2083};20842085KUNIT_ARRAY_PARAM(halo_all_num_blocks,2086halo_all_num_blocks_param_cases,2087cs_dsp_mem_param_desc);20882089static const struct cs_dsp_wmfw_test_param packed_xy_num_blocks_param_cases[] = {2090{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 1 },2091{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 2 },2092{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 3 },2093{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 4 },2094{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 5 },2095{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 6 },2096{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 12 },2097{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 13 },2098{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 14 },2099{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 15 },2100{ .mem_type = WMFW_HALO_XM_PACKED, .num_blocks = 16 },21012102{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 1 },2103{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 2 },2104{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 3 },2105{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 4 },2106{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 5 },2107{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 6 },2108{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 12 },2109{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 13 },2110{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 14 },2111{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 15 },2112{ .mem_type = WMFW_HALO_YM_PACKED, .num_blocks = 16 },2113};21142115KUNIT_ARRAY_PARAM(packed_xy_num_blocks,2116packed_xy_num_blocks_param_cases,2117cs_dsp_mem_param_desc);21182119static struct kunit_case cs_dsp_wmfw_test_cases_halo[] = {2120KUNIT_CASE(wmfw_write_xm_header_unpacked),21212122KUNIT_CASE_PARAM(wmfw_write_one_payload,2123halo_all_num_blocks_gen_params),2124KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads,2125halo_all_num_blocks_gen_params),2126KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads_reverse,2127halo_all_num_blocks_gen_params),2128KUNIT_CASE_PARAM(wmfw_write_multiple_payloads_sparse_unordered,2129halo_all_num_blocks_gen_params),21302131KUNIT_CASE(wmfw_write_all_packed_pm),2132KUNIT_CASE(wmfw_write_multiple_packed_unpacked_mem),21332134KUNIT_CASE_PARAM(wmfw_write_packed_1_unpacked_trailing,2135packed_xy_num_blocks_gen_params),2136KUNIT_CASE_PARAM(wmfw_write_packed_2_unpacked_trailing,2137packed_xy_num_blocks_gen_params),2138KUNIT_CASE_PARAM(wmfw_write_packed_3_unpacked_trailing,2139packed_xy_num_blocks_gen_params),2140KUNIT_CASE_PARAM(wmfw_write_packed_2_single_unpacked_trailing,2141packed_xy_num_blocks_gen_params),2142KUNIT_CASE_PARAM(wmfw_write_packed_3_single_unpacked_trailing,2143packed_xy_num_blocks_gen_params),2144KUNIT_CASE_PARAM(wmfw_write_packed_1_unpacked_leading,2145packed_xy_num_blocks_gen_params),2146KUNIT_CASE_PARAM(wmfw_write_packed_2_unpacked_leading,2147packed_xy_num_blocks_gen_params),2148KUNIT_CASE_PARAM(wmfw_write_packed_3_unpacked_leading,2149packed_xy_num_blocks_gen_params),2150KUNIT_CASE_PARAM(wmfw_write_packed_2_single_unpacked_leading,2151packed_xy_num_blocks_gen_params),2152KUNIT_CASE_PARAM(wmfw_write_packed_3_single_unpacked_leading,2153packed_xy_num_blocks_gen_params),21542155KUNIT_CASE(wmfw_load_with_info),21562157{ } /* terminator */2158};21592160static struct kunit_case cs_dsp_wmfw_test_cases_adsp2[] = {2161KUNIT_CASE(wmfw_write_xm_header_unpacked),2162KUNIT_CASE_PARAM(wmfw_write_one_payload,2163adsp2_all_num_blocks_gen_params),2164KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads,2165adsp2_all_num_blocks_gen_params),2166KUNIT_CASE_PARAM(wmfw_write_multiple_oneblock_payloads_reverse,2167adsp2_all_num_blocks_gen_params),2168KUNIT_CASE_PARAM(wmfw_write_multiple_payloads_sparse_unordered,2169adsp2_all_num_blocks_gen_params),21702171KUNIT_CASE(wmfw_write_all_unpacked_pm),2172KUNIT_CASE(wmfw_write_multiple_unpacked_mem),21732174KUNIT_CASE(wmfw_load_with_info),21752176{ } /* terminator */2177};21782179static struct kunit_suite cs_dsp_wmfw_test_halo = {2180.name = "cs_dsp_wmfwV3_halo",2181.init = cs_dsp_wmfw_test_halo_init,2182.exit = cs_dsp_wmfw_test_exit,2183.test_cases = cs_dsp_wmfw_test_cases_halo,2184};21852186static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw0 = {2187.name = "cs_dsp_wmfwV0_adsp2_32bit",2188.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init,2189.exit = cs_dsp_wmfw_test_exit,2190.test_cases = cs_dsp_wmfw_test_cases_adsp2,2191};21922193static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw1 = {2194.name = "cs_dsp_wmfwV1_adsp2_32bit",2195.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init,2196.exit = cs_dsp_wmfw_test_exit,2197.test_cases = cs_dsp_wmfw_test_cases_adsp2,2198};21992200static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw2 = {2201.name = "cs_dsp_wmfwV2_adsp2_32bit",2202.init = cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init,2203.exit = cs_dsp_wmfw_test_exit,2204.test_cases = cs_dsp_wmfw_test_cases_adsp2,2205};22062207static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw0 = {2208.name = "cs_dsp_wmfwV0_adsp2_16bit",2209.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init,2210.exit = cs_dsp_wmfw_test_exit,2211.test_cases = cs_dsp_wmfw_test_cases_adsp2,2212};22132214static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw1 = {2215.name = "cs_dsp_wmfwV1_adsp2_16bit",2216.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init,2217.exit = cs_dsp_wmfw_test_exit,2218.test_cases = cs_dsp_wmfw_test_cases_adsp2,2219};22202221static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw2 = {2222.name = "cs_dsp_wmfwV2_adsp2_16bit",2223.init = cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init,2224.exit = cs_dsp_wmfw_test_exit,2225.test_cases = cs_dsp_wmfw_test_cases_adsp2,2226};22272228kunit_test_suites(&cs_dsp_wmfw_test_halo,2229&cs_dsp_wmfw_test_adsp2_32bit_wmfw0,2230&cs_dsp_wmfw_test_adsp2_32bit_wmfw1,2231&cs_dsp_wmfw_test_adsp2_32bit_wmfw2,2232&cs_dsp_wmfw_test_adsp2_16bit_wmfw0,2233&cs_dsp_wmfw_test_adsp2_16bit_wmfw1,2234&cs_dsp_wmfw_test_adsp2_16bit_wmfw2);223522362237