Path: blob/master/drivers/firmware/cirrus/test/cs_dsp_test_bin.c
51431 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.67#include <kunit/device.h>8#include <kunit/resource.h>9#include <kunit/test.h>10#include <linux/build_bug.h>11#include <linux/firmware/cirrus/cs_dsp.h>12#include <linux/firmware/cirrus/cs_dsp_test_utils.h>13#include <linux/firmware/cirrus/wmfw.h>14#include <linux/firmware.h>15#include <linux/math.h>16#include <linux/random.h>17#include <linux/regmap.h>1819#include "../cs_dsp.h"2021/*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 a XM header with an algorithm list in the cached regmap.26* 3) Create dummy wmfw file to satisfy cs_dsp.27* 4) Create bin file content.28* 5) Call cs_dsp_power_up() with the bin file.29* 6) Readback the cached value of registers that should have been written and30* check they have the correct value.31* 7) All the registers that are expected to have been written are dropped from32* the cache (including the XM header). This should leave the cache clean.33* 8) If the cache is still dirty there have been unexpected writes.34*35* There are multiple different schemes used for addressing across36* ADSP2 and Halo Core DSPs:37*38* dsp words: The addressing scheme used by the DSP, pointers and lengths39* in DSP memory use this. A memory region (XM, YM, ZM) is40* also required to create a unique DSP memory address.41* registers: Addresses in the register map. Older ADSP2 devices have42* 16-bit registers with an address stride of 1. Newer ADSP243* devices have 32-bit registers with an address stride of 2.44* Halo Core devices have 32-bit registers with a stride of 4.45* unpacked: Registers that have a 1:1 mapping to DSP words46* packed: Registers that pack multiple DSP words more efficiently into47* multiple 32-bit registers. Because of this the relationship48* between a packed _register_ address and the corresponding49* _dsp word_ address is different from unpacked registers.50* Packed registers can only be accessed as a group of51* multiple registers, therefore can only read/write a group52* of multiple DSP words.53* Packed registers only exist on Halo Core DSPs.54*55* Addresses can also be relative to the start of an algorithm, and this56* can be expressed in dsp words, register addresses, or bytes.57*/5859KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)60KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)6162struct cs_dsp_test_local {63struct cs_dsp_mock_bin_builder *bin_builder;64struct cs_dsp_mock_wmfw_builder *wmfw_builder;65struct firmware *wmfw;66};6768struct bin_test_param {69const char *name;70int mem_type;71unsigned int offset_words;72int alg_idx;73void (*add_patch)(struct cs_dsp_mock_bin_builder *builder,74unsigned int alg_id, unsigned int alg_ver,75int mem_region, unsigned int reg_addr_offset,76const void *payload_data, size_t payload_len_bytes);77};7879static const struct cs_dsp_mock_alg_def bin_test_mock_algs[] = {80{81.id = 0xfafa,82.ver = 0x100000,83.xm_size_words = 164,84.ym_size_words = 164,85.zm_size_words = 164,86},87{88.id = 0xfbfb,89.ver = 0x100000,90.xm_size_words = 99,91.ym_size_words = 99,92.zm_size_words = 99,93},94{95.id = 0xc321,96.ver = 0x100000,97.xm_size_words = 120,98.ym_size_words = 120,99.zm_size_words = 120,100},101{102.id = 0xb123,103.ver = 0x100000,104.xm_size_words = 96,105.ym_size_words = 96,106.zm_size_words = 96,107},108};109110/*111* Convert number of DSP words to number of packed registers rounded112* down to the nearest register.113* There are 3 registers for every 4 packed words.114*/115static unsigned int _num_words_to_num_packed_regs(unsigned int num_dsp_words)116{117return (num_dsp_words * 3) / 4;118}119120/* bin file that patches a single DSP word */121static void bin_patch_one_word(struct kunit *test)122{123struct cs_dsp_test *priv = test->priv;124const struct bin_test_param *param = test->param_value;125unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);126u32 reg_val, payload_data;127unsigned int alg_base_words, reg_addr;128struct firmware *fw;129130get_random_bytes(&payload_data, sizeof(payload_data));131132alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,133bin_test_mock_algs[param->alg_idx].id,134param->mem_type);135136param->add_patch(priv->local->bin_builder,137bin_test_mock_algs[param->alg_idx].id,138bin_test_mock_algs[param->alg_idx].ver,139param->mem_type,140param->offset_words * reg_inc_per_word,141&payload_data, sizeof(payload_data));142143fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);144KUNIT_ASSERT_EQ(test,145cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",146fw, "mock_bin", "misc"),1470);148149/* Content of registers should match payload_data */150reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +151((alg_base_words + param->offset_words) * reg_inc_per_word);152reg_val = 0;153KUNIT_EXPECT_EQ(test,154regmap_raw_read(priv->dsp->regmap, reg_addr,155®_val, sizeof(reg_val)),1560);157KUNIT_EXPECT_EQ(test, reg_val, payload_data);158159/* Drop expected writes and the cache should then be clean */160cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);161cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);162163KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));164}165166/* bin file with a single payload that patches consecutive words */167static void bin_patch_one_multiword(struct kunit *test)168{169struct cs_dsp_test *priv = test->priv;170const struct bin_test_param *param = test->param_value;171unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);172u32 payload_data[16], readback[16];173unsigned int alg_base_words, reg_addr;174struct firmware *fw;175176static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));177178get_random_bytes(&payload_data, sizeof(payload_data));179memset(readback, 0, sizeof(readback));180181alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,182bin_test_mock_algs[param->alg_idx].id,183param->mem_type);184185param->add_patch(priv->local->bin_builder,186bin_test_mock_algs[param->alg_idx].id,187bin_test_mock_algs[param->alg_idx].ver,188param->mem_type,189param->offset_words * reg_inc_per_word,190payload_data, sizeof(payload_data));191192fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);193KUNIT_ASSERT_EQ(test,194cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",195fw, "mock_bin", "misc"),1960);197198/* Content of registers should match payload_data */199reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +200((alg_base_words + param->offset_words) * reg_inc_per_word);201KUNIT_EXPECT_EQ(test,202regmap_raw_read(priv->dsp->regmap, reg_addr, readback,203sizeof(readback)),2040);205KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));206207/* Drop expected writes and the cache should then be clean */208cs_dsp_mock_regmap_drop_range(priv, reg_addr,209reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));210cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);211KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));212}213214/* bin file with a multiple one-word payloads that patch consecutive words */215static void bin_patch_multi_oneword(struct kunit *test)216{217struct cs_dsp_test *priv = test->priv;218const struct bin_test_param *param = test->param_value;219unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);220u32 payload_data[16], readback[16];221unsigned int alg_base_words, reg_addr;222struct firmware *fw;223int i;224225static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));226227get_random_bytes(&payload_data, sizeof(payload_data));228memset(readback, 0, sizeof(readback));229230alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,231bin_test_mock_algs[param->alg_idx].id,232param->mem_type);233234/* Add one payload per word */235for (i = 0; i < ARRAY_SIZE(payload_data); ++i) {236param->add_patch(priv->local->bin_builder,237bin_test_mock_algs[param->alg_idx].id,238bin_test_mock_algs[param->alg_idx].ver,239param->mem_type,240(param->offset_words + i) * reg_inc_per_word,241&payload_data[i], sizeof(payload_data[i]));242}243244fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);245KUNIT_ASSERT_EQ(test,246cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",247fw, "mock_bin", "misc"),2480);249250/* Content of registers should match payload_data */251reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +252((alg_base_words + param->offset_words) * reg_inc_per_word);253KUNIT_EXPECT_EQ(test,254regmap_raw_read(priv->dsp->regmap, reg_addr, readback,255sizeof(readback)),2560);257KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));258259/* Drop expected writes and the cache should then be clean */260cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);261cs_dsp_mock_regmap_drop_range(priv, reg_addr,262reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));263KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));264}265266/*267* bin file with a multiple one-word payloads that patch a block of consecutive268* words but the payloads are not in address order.269*/270static void bin_patch_multi_oneword_unordered(struct kunit *test)271{272struct cs_dsp_test *priv = test->priv;273const struct bin_test_param *param = test->param_value;274unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);275u32 payload_data[16], readback[16];276static const u8 word_order[] = { 10, 2, 12, 4, 0, 11, 6, 1, 3, 15, 5, 13, 8, 7, 9, 14 };277unsigned int alg_base_words, reg_addr;278struct firmware *fw;279int i;280281static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));282static_assert(ARRAY_SIZE(word_order) == ARRAY_SIZE(payload_data));283284get_random_bytes(&payload_data, sizeof(payload_data));285memset(readback, 0, sizeof(readback));286287alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,288bin_test_mock_algs[param->alg_idx].id,289param->mem_type);290291/* Add one payload per word */292for (i = 0; i < ARRAY_SIZE(word_order); ++i) {293param->add_patch(priv->local->bin_builder,294bin_test_mock_algs[param->alg_idx].id,295bin_test_mock_algs[param->alg_idx].ver,296param->mem_type,297(param->offset_words + word_order[i]) *298reg_inc_per_word,299&payload_data[word_order[i]], sizeof(payload_data[0]));300}301302fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);303KUNIT_ASSERT_EQ(test,304cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",305fw, "mock_bin", "misc"),3060);307308/* Content of registers should match payload_data */309reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +310((alg_base_words + param->offset_words) * reg_inc_per_word);311KUNIT_EXPECT_EQ(test,312regmap_raw_read(priv->dsp->regmap, reg_addr, readback,313sizeof(readback)),3140);315KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));316317/* Drop expected writes and the cache should then be clean */318cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);319cs_dsp_mock_regmap_drop_range(priv, reg_addr,320reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));321KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));322}323324/*325* bin file with a multiple one-word payloads. The payloads are not in address326* order and collectively do not patch a contiguous block of memory.327*/328static void bin_patch_multi_oneword_sparse_unordered(struct kunit *test)329{330struct cs_dsp_test *priv = test->priv;331const struct bin_test_param *param = test->param_value;332unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);333static const u8 word_offsets[] = {33411, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,33554, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,33629, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22337};338u32 payload_data[44];339unsigned int alg_base_words, reg_addr;340struct firmware *fw;341u32 reg_val;342int i;343344static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(payload_data));345346get_random_bytes(&payload_data, sizeof(payload_data));347348alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,349bin_test_mock_algs[param->alg_idx].id,350param->mem_type);351352/* Add one payload per word */353for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {354param->add_patch(priv->local->bin_builder,355bin_test_mock_algs[param->alg_idx].id,356bin_test_mock_algs[param->alg_idx].ver,357param->mem_type,358word_offsets[i] * reg_inc_per_word,359&payload_data[i], sizeof(payload_data[i]));360}361362fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);363KUNIT_ASSERT_EQ(test,364cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",365fw, "mock_bin", "misc"),3660);367368/* Content of registers should match payload_data */369for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {370reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +371((alg_base_words + word_offsets[i]) * reg_inc_per_word);372reg_val = 0;373KUNIT_EXPECT_EQ(test,374regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,375sizeof(reg_val)),3760);377KUNIT_EXPECT_MEMEQ(test, ®_val, &payload_data[i], sizeof(reg_val));378379/* Drop expected writes from the cache */380cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);381}382383/* Drop expected writes and the cache should then be clean */384cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);385KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));386}387388/*389* bin file that patches a single DSP word in each of the memory regions390* of one algorithm.391*/392static void bin_patch_one_word_multiple_mems(struct kunit *test)393{394struct cs_dsp_test *priv = test->priv;395const struct bin_test_param *param = test->param_value;396unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);397unsigned int alg_xm_base_words, alg_ym_base_words, alg_zm_base_words;398unsigned int reg_addr;399u32 payload_data[3];400struct firmware *fw;401u32 reg_val;402403get_random_bytes(&payload_data, sizeof(payload_data));404405alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,406bin_test_mock_algs[param->alg_idx].id,407WMFW_ADSP2_XM);408alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,409bin_test_mock_algs[param->alg_idx].id,410WMFW_ADSP2_YM);411412if (cs_dsp_mock_has_zm(priv)) {413alg_zm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,414bin_test_mock_algs[param->alg_idx].id,415WMFW_ADSP2_ZM);416} else {417alg_zm_base_words = 0;418}419420/* Add words to XM, YM and ZM */421param->add_patch(priv->local->bin_builder,422bin_test_mock_algs[param->alg_idx].id,423bin_test_mock_algs[param->alg_idx].ver,424WMFW_ADSP2_XM,425param->offset_words * reg_inc_per_word,426&payload_data[0], sizeof(payload_data[0]));427428param->add_patch(priv->local->bin_builder,429bin_test_mock_algs[param->alg_idx].id,430bin_test_mock_algs[param->alg_idx].ver,431WMFW_ADSP2_YM,432param->offset_words * reg_inc_per_word,433&payload_data[1], sizeof(payload_data[1]));434435if (cs_dsp_mock_has_zm(priv)) {436param->add_patch(priv->local->bin_builder,437bin_test_mock_algs[param->alg_idx].id,438bin_test_mock_algs[param->alg_idx].ver,439WMFW_ADSP2_ZM,440param->offset_words * reg_inc_per_word,441&payload_data[2], sizeof(payload_data[2]));442}443444fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);445KUNIT_ASSERT_EQ(test,446cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",447fw, "mock_bin", "misc"),4480);449450/* Content of registers should match payload_data */451reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM) +452((alg_xm_base_words + param->offset_words) * reg_inc_per_word);453reg_val = 0;454KUNIT_EXPECT_EQ(test,455regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),4560);457KUNIT_EXPECT_EQ(test, reg_val, payload_data[0]);458459cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);460461reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM) +462((alg_ym_base_words + param->offset_words) * reg_inc_per_word);463reg_val = 0;464KUNIT_EXPECT_EQ(test,465regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),4660);467KUNIT_EXPECT_EQ(test, reg_val, payload_data[1]);468469cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);470471if (cs_dsp_mock_has_zm(priv)) {472reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM) +473((alg_zm_base_words + param->offset_words) * reg_inc_per_word);474reg_val = 0;475KUNIT_EXPECT_EQ(test,476regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,477sizeof(reg_val)),4780);479KUNIT_EXPECT_EQ(test, reg_val, payload_data[2]);480481/* Drop expected writes from the cache */482cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);483}484485/* Drop expected writes and the cache should then be clean */486cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);487KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));488}489490/*491* bin file that patches a single DSP word in multiple algorithms.492*/493static void bin_patch_one_word_multiple_algs(struct kunit *test)494{495struct cs_dsp_test *priv = test->priv;496const struct bin_test_param *param = test->param_value;497u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];498unsigned int alg_base_words;499unsigned int reg_inc_per_word, reg_addr;500struct firmware *fw;501u32 reg_val;502int i;503504get_random_bytes(&payload_data, sizeof(payload_data));505506/* Add one payload per algorithm */507for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {508reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);509510param->add_patch(priv->local->bin_builder,511bin_test_mock_algs[i].id,512bin_test_mock_algs[i].ver,513param->mem_type,514param->offset_words * reg_inc_per_word,515&payload_data[i], sizeof(payload_data[i]));516}517518fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);519KUNIT_ASSERT_EQ(test,520cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",521fw, "mock_bin", "misc"),5220);523524/* Content of registers should match payload_data */525for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {526alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,527bin_test_mock_algs[i].id,528param->mem_type);529reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);530reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +531((alg_base_words + param->offset_words) * reg_inc_per_word);532reg_val = 0;533KUNIT_EXPECT_EQ(test,534regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,535sizeof(reg_val)),5360);537KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);538539/* Drop expected writes from the cache */540cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);541}542543/* Drop expected writes and the cache should then be clean */544cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);545KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));546}547548/*549* bin file that patches a single DSP word in multiple algorithms.550* The algorithms are not patched in the same order they appear in the XM header.551*/552static void bin_patch_one_word_multiple_algs_unordered(struct kunit *test)553{554struct cs_dsp_test *priv = test->priv;555const struct bin_test_param *param = test->param_value;556static const u8 alg_order[] = { 3, 0, 2, 1 };557u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];558unsigned int alg_base_words;559unsigned int reg_inc_per_word, reg_addr;560struct firmware *fw;561u32 reg_val;562int i, alg_idx;563564static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));565566get_random_bytes(&payload_data, sizeof(payload_data));567568/* Add one payload per algorithm */569for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {570alg_idx = alg_order[i];571reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);572573param->add_patch(priv->local->bin_builder,574bin_test_mock_algs[alg_idx].id,575bin_test_mock_algs[alg_idx].ver,576param->mem_type,577param->offset_words * reg_inc_per_word,578&payload_data[i], sizeof(payload_data[i]));579}580581fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);582KUNIT_ASSERT_EQ(test,583cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",584fw, "mock_bin", "misc"),5850);586587/* Content of registers should match payload_data */588for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {589alg_idx = alg_order[i];590alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,591bin_test_mock_algs[alg_idx].id,592param->mem_type);593reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);594reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +595((alg_base_words + param->offset_words) * reg_inc_per_word);596reg_val = 0;597KUNIT_EXPECT_EQ(test,598regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,599sizeof(reg_val)),6000);601KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);602603/* Drop expected writes from the cache */604cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);605}606607/* Drop expected writes and the cache should then be clean */608cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);609KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));610}611612/* bin file that patches a single packed block of DSP words */613static void bin_patch_1_packed(struct kunit *test)614{615struct cs_dsp_test *priv = test->priv;616const struct bin_test_param *param = test->param_value;617u32 packed_payload[3], readback[3];618unsigned int alg_base_words, patch_pos_words;619unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;620unsigned int reg_addr;621struct firmware *fw;622623static_assert(sizeof(readback) == sizeof(packed_payload));624625get_random_bytes(packed_payload, sizeof(packed_payload));626627alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,628bin_test_mock_algs[param->alg_idx].id,629param->mem_type);630alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);631632/* Round patch start word up to a packed boundary */633patch_pos_words = round_up(alg_base_words + param->offset_words, 4);634patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);635636param->add_patch(priv->local->bin_builder,637bin_test_mock_algs[param->alg_idx].id,638bin_test_mock_algs[param->alg_idx].ver,639param->mem_type,640(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,641packed_payload, sizeof(packed_payload));642643fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);644KUNIT_ASSERT_EQ(test,645cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",646fw, "mock_bin", "misc"),6470);648649/* Content of registers should match payload_data */650reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +651(patch_pos_in_packed_regs * 4);652memset(readback, 0, sizeof(readback));653KUNIT_EXPECT_EQ(test,654regmap_raw_read(priv->dsp->regmap, reg_addr, readback,655sizeof(readback)),6560);657KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));658659/* Drop expected writes and the cache should then be clean */660cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);661cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));662KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));663}664665/*666* Patch data that is one word longer than a packed block using one667* packed block followed by one unpacked word.668*/669static void bin_patch_1_packed_1_single_trailing(struct kunit *test)670{671struct cs_dsp_test *priv = test->priv;672const struct bin_test_param *param = test->param_value;673unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);674u32 packed_payload[3], unpacked_payload[1], readback[3];675unsigned int alg_base_words, patch_pos_words;676unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;677unsigned int reg_addr;678struct firmware *fw;679680static_assert(sizeof(readback) == sizeof(packed_payload));681static_assert(sizeof(readback) >= sizeof(unpacked_payload));682683get_random_bytes(packed_payload, sizeof(packed_payload));684get_random_bytes(unpacked_payload, sizeof(unpacked_payload));685686alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,687bin_test_mock_algs[param->alg_idx].id,688param->mem_type);689alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);690691/* Round patch start word up to a packed boundary */692patch_pos_words = round_up(alg_base_words + param->offset_words, 4);693patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);694695/* Patch packed block */696param->add_patch(priv->local->bin_builder,697bin_test_mock_algs[param->alg_idx].id,698bin_test_mock_algs[param->alg_idx].ver,699param->mem_type,700(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,701&packed_payload, sizeof(packed_payload));702703/* ... and the unpacked word following that */704param->add_patch(priv->local->bin_builder,705bin_test_mock_algs[param->alg_idx].id,706bin_test_mock_algs[param->alg_idx].ver,707unpacked_mem_type,708((patch_pos_words + 4) - alg_base_words) * 4,709unpacked_payload, sizeof(unpacked_payload));710711fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);712KUNIT_ASSERT_EQ(test,713cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",714fw, "mock_bin", "misc"),7150);716717/* Content of packed registers should match packed_payload */718reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +719(patch_pos_in_packed_regs * 4);720memset(readback, 0, sizeof(readback));721KUNIT_EXPECT_EQ(test,722regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),7230);724KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));725726cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));727728/* Content of unpacked registers should match unpacked_payload */729reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +730(patch_pos_words + 4) * 4;731memset(readback, 0, sizeof(readback));732KUNIT_EXPECT_EQ(test,733regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,734sizeof(unpacked_payload)),7350);736KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));737738cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));739740/* Drop expected writes and the cache should then be clean */741cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);742KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));743}744745/*746* Patch data that is two words longer than a packed block using one747* packed block followed by two blocks of one unpacked word.748*/749static void bin_patch_1_packed_2_single_trailing(struct kunit *test)750{751struct cs_dsp_test *priv = test->priv;752const struct bin_test_param *param = test->param_value;753unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);754u32 packed_payload[3], unpacked_payloads[2], readback[3];755unsigned int alg_base_words, patch_pos_words;756unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;757unsigned int reg_addr;758struct firmware *fw;759760static_assert(sizeof(readback) == sizeof(packed_payload));761static_assert(sizeof(readback) >= sizeof(unpacked_payloads));762763get_random_bytes(packed_payload, sizeof(packed_payload));764get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));765766alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,767bin_test_mock_algs[param->alg_idx].id,768param->mem_type);769alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);770771/* Round patch start word up to a packed boundary */772patch_pos_words = round_up(alg_base_words + param->offset_words, 4);773patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);774775/* Patch packed block */776param->add_patch(priv->local->bin_builder,777bin_test_mock_algs[param->alg_idx].id,778bin_test_mock_algs[param->alg_idx].ver,779param->mem_type,780(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,781&packed_payload, sizeof(packed_payload));782783/* ... and the unpacked words following that */784param->add_patch(priv->local->bin_builder,785bin_test_mock_algs[param->alg_idx].id,786bin_test_mock_algs[param->alg_idx].ver,787unpacked_mem_type,788((patch_pos_words + 4) - alg_base_words) * 4,789&unpacked_payloads[0], sizeof(unpacked_payloads[0]));790791param->add_patch(priv->local->bin_builder,792bin_test_mock_algs[param->alg_idx].id,793bin_test_mock_algs[param->alg_idx].ver,794unpacked_mem_type,795((patch_pos_words + 5) - alg_base_words) * 4,796&unpacked_payloads[1], sizeof(unpacked_payloads[1]));797798fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);799KUNIT_ASSERT_EQ(test,800cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",801fw, "mock_bin", "misc"),8020);803804/* Content of packed registers should match packed_payload */805reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +806(patch_pos_in_packed_regs * 4);807memset(readback, 0, sizeof(readback));808KUNIT_EXPECT_EQ(test,809regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),8100);811KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));812813/* Drop expected writes from the cache */814cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));815816/* Content of unpacked registers should match unpacked_payloads */817reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +818(patch_pos_words + 4) * 4;819memset(readback, 0, sizeof(readback));820KUNIT_EXPECT_EQ(test,821regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,822sizeof(unpacked_payloads)),8230);824KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));825826/* Drop expected writes from the cache */827cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));828829/* Drop expected writes and the cache should then be clean */830cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);831KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));832}833834/*835* Patch data that is three words longer than a packed block using one836* packed block followed by three blocks of one unpacked word.837*/838static void bin_patch_1_packed_3_single_trailing(struct kunit *test)839{840struct cs_dsp_test *priv = test->priv;841const struct bin_test_param *param = test->param_value;842unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);843u32 packed_payload[3], unpacked_payloads[3], readback[3];844unsigned int alg_base_words, patch_pos_words;845unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;846unsigned int reg_addr;847struct firmware *fw;848849static_assert(sizeof(readback) == sizeof(packed_payload));850static_assert(sizeof(readback) >= sizeof(unpacked_payloads));851852get_random_bytes(packed_payload, sizeof(packed_payload));853get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));854855alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,856bin_test_mock_algs[param->alg_idx].id,857param->mem_type);858alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);859860/* Round patch start word up to a packed boundary */861patch_pos_words = round_up(alg_base_words + param->offset_words, 4);862patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);863864/* Patch packed block */865param->add_patch(priv->local->bin_builder,866bin_test_mock_algs[param->alg_idx].id,867bin_test_mock_algs[param->alg_idx].ver,868param->mem_type,869(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,870&packed_payload, sizeof(packed_payload));871872/* ... and the unpacked words following that */873param->add_patch(priv->local->bin_builder,874bin_test_mock_algs[param->alg_idx].id,875bin_test_mock_algs[param->alg_idx].ver,876unpacked_mem_type,877((patch_pos_words + 4) - alg_base_words) * 4,878&unpacked_payloads[0], sizeof(unpacked_payloads[0]));879880param->add_patch(priv->local->bin_builder,881bin_test_mock_algs[param->alg_idx].id,882bin_test_mock_algs[param->alg_idx].ver,883unpacked_mem_type,884((patch_pos_words + 5) - alg_base_words) * 4,885&unpacked_payloads[1], sizeof(unpacked_payloads[1]));886887param->add_patch(priv->local->bin_builder,888bin_test_mock_algs[param->alg_idx].id,889bin_test_mock_algs[param->alg_idx].ver,890unpacked_mem_type,891((patch_pos_words + 6) - alg_base_words) * 4,892&unpacked_payloads[2], sizeof(unpacked_payloads[2]));893894fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);895KUNIT_ASSERT_EQ(test,896cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",897fw, "mock_bin", "misc"),8980);899900/* Content of packed registers should match packed_payload */901reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +902(patch_pos_in_packed_regs * 4);903memset(readback, 0, sizeof(readback));904KUNIT_EXPECT_EQ(test,905regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),9060);907KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));908909/* Drop expected writes from the cache */910cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));911912/* Content of unpacked registers should match unpacked_payloads */913reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +914(patch_pos_words + 4) * 4;915memset(readback, 0, sizeof(readback));916KUNIT_EXPECT_EQ(test,917regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,918sizeof(unpacked_payloads)),9190);920KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));921922/* Drop expected writes from the cache */923cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));924925/* Drop expected writes and the cache should then be clean */926cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);927KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));928}929930/*931* Patch data that is two words longer than a packed block using one932* packed block followed by a block of two unpacked words.933*/934static void bin_patch_1_packed_2_trailing(struct kunit *test)935{936struct cs_dsp_test *priv = test->priv;937const struct bin_test_param *param = test->param_value;938unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);939u32 packed_payload[3], unpacked_payload[2], readback[3];940unsigned int alg_base_words, patch_pos_words;941unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;942unsigned int reg_addr;943struct firmware *fw;944945static_assert(sizeof(readback) == sizeof(packed_payload));946static_assert(sizeof(readback) >= sizeof(unpacked_payload));947948get_random_bytes(packed_payload, sizeof(packed_payload));949get_random_bytes(unpacked_payload, sizeof(unpacked_payload));950951alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,952bin_test_mock_algs[param->alg_idx].id,953param->mem_type);954alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);955956/* Round patch start word up to a packed boundary */957patch_pos_words = round_up(alg_base_words + param->offset_words, 4);958patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);959960/* Patch packed block */961param->add_patch(priv->local->bin_builder,962bin_test_mock_algs[param->alg_idx].id,963bin_test_mock_algs[param->alg_idx].ver,964param->mem_type,965(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,966&packed_payload, sizeof(packed_payload));967968/* ... and the unpacked words following that */969param->add_patch(priv->local->bin_builder,970bin_test_mock_algs[param->alg_idx].id,971bin_test_mock_algs[param->alg_idx].ver,972unpacked_mem_type,973((patch_pos_words + 4) - alg_base_words) * 4,974unpacked_payload, sizeof(unpacked_payload));975976fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);977KUNIT_ASSERT_EQ(test,978cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",979fw, "mock_bin", "misc"),9800);981982/* Content of packed registers should match packed_payload */983reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +984(patch_pos_in_packed_regs * 4);985memset(readback, 0, sizeof(readback));986KUNIT_EXPECT_EQ(test,987regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),9880);989KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));990991/* Drop expected writes from the cache */992cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));993994/* Content of unpacked registers should match unpacked_payload */995reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +996(patch_pos_words + 4) * 4;997memset(readback, 0, sizeof(readback));998KUNIT_EXPECT_EQ(test,999regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1000sizeof(unpacked_payload)),10010);1002KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));10031004/* Drop expected writes from the cache */1005cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));10061007/* Drop expected writes and the cache should then be clean */1008cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1009KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1010}10111012/*1013* Patch data that is three words longer than a packed block using one1014* packed block followed by a block of three unpacked words.1015*/1016static void bin_patch_1_packed_3_trailing(struct kunit *test)1017{1018struct cs_dsp_test *priv = test->priv;1019const struct bin_test_param *param = test->param_value;1020unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1021u32 packed_payload[3], unpacked_payload[3], readback[3];1022unsigned int alg_base_words, patch_pos_words;1023unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1024unsigned int reg_addr;1025struct firmware *fw;10261027static_assert(sizeof(readback) == sizeof(packed_payload));1028static_assert(sizeof(readback) >= sizeof(unpacked_payload));10291030get_random_bytes(packed_payload, sizeof(packed_payload));1031get_random_bytes(unpacked_payload, sizeof(unpacked_payload));10321033alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1034bin_test_mock_algs[param->alg_idx].id,1035param->mem_type);1036alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);10371038/* Round patch start word up to a packed boundary */1039patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1040patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);10411042/* Patch packed block */1043param->add_patch(priv->local->bin_builder,1044bin_test_mock_algs[param->alg_idx].id,1045bin_test_mock_algs[param->alg_idx].ver,1046param->mem_type,1047(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1048&packed_payload, sizeof(packed_payload));10491050/* ... and the unpacked words following that */1051param->add_patch(priv->local->bin_builder,1052bin_test_mock_algs[param->alg_idx].id,1053bin_test_mock_algs[param->alg_idx].ver,1054unpacked_mem_type,1055((patch_pos_words + 4) - alg_base_words) * 4,1056unpacked_payload, sizeof(unpacked_payload));10571058fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1059KUNIT_ASSERT_EQ(test,1060cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1061fw, "mock_bin", "misc"),10620);10631064/* Content of packed registers should match packed_payload */1065reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1066(patch_pos_in_packed_regs * 4);1067memset(readback, 0, sizeof(readback));1068KUNIT_EXPECT_EQ(test,1069regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),10700);1071KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));10721073/* Drop expected writes from the cache */1074cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));10751076/* Content of unpacked registers should match unpacked_payload */1077reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1078(patch_pos_words + 4) * 4;1079memset(readback, 0, sizeof(readback));1080KUNIT_EXPECT_EQ(test,1081regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1082sizeof(unpacked_payload)),10830);1084KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));10851086/* Drop expected writes from the cache */1087cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));10881089/* Drop expected writes and the cache should then be clean */1090cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1091KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1092}10931094/*1095* Patch data that starts one word before a packed boundary using one1096* unpacked word followed by one packed block.1097*/1098static void bin_patch_1_single_leading_1_packed(struct kunit *test)1099{1100struct cs_dsp_test *priv = test->priv;1101const struct bin_test_param *param = test->param_value;1102unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1103u32 packed_payload[3], unpacked_payload[1], readback[3];1104unsigned int alg_base_words, packed_patch_pos_words;1105unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1106unsigned int reg_addr;1107struct firmware *fw;11081109static_assert(sizeof(readback) == sizeof(packed_payload));1110static_assert(sizeof(readback) >= sizeof(unpacked_payload));11111112get_random_bytes(packed_payload, sizeof(packed_payload));1113get_random_bytes(unpacked_payload, sizeof(unpacked_payload));1114memset(readback, 0, sizeof(readback));11151116alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1117bin_test_mock_algs[param->alg_idx].id,1118param->mem_type);1119alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);11201121/* Round packed start word up to a packed boundary and move to the next boundary */1122packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;11231124/* Patch the leading unpacked word */1125param->add_patch(priv->local->bin_builder,1126bin_test_mock_algs[param->alg_idx].id,1127bin_test_mock_algs[param->alg_idx].ver,1128unpacked_mem_type,1129((packed_patch_pos_words - 1) - alg_base_words) * 4,1130unpacked_payload, sizeof(unpacked_payload));1131/* ... then the packed block */1132patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1133param->add_patch(priv->local->bin_builder,1134bin_test_mock_algs[param->alg_idx].id,1135bin_test_mock_algs[param->alg_idx].ver,1136param->mem_type,1137(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1138&packed_payload, sizeof(packed_payload));11391140fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1141KUNIT_ASSERT_EQ(test,1142cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1143fw, "mock_bin", "misc"),11440);11451146/* Content of packed registers should match packed_payload */1147reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1148(patch_pos_in_packed_regs * 4);1149KUNIT_EXPECT_EQ(test,1150regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),11510);1152KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));11531154/* Drop expected writes from the cache */1155cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));11561157/* Content of unpacked registers should match unpacked_payload */1158reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1159(packed_patch_pos_words - 1) * 4;1160KUNIT_EXPECT_EQ(test,1161regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1162sizeof(unpacked_payload)),11630);1164KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));11651166/* Drop expected writes from the cache */1167cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));11681169/* Drop expected writes and the cache should then be clean */1170cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1171KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1172}11731174/*1175* Patch data that starts two words before a packed boundary using two1176* unpacked words followed by one packed block.1177*/1178static void bin_patch_2_single_leading_1_packed(struct kunit *test)1179{1180struct cs_dsp_test *priv = test->priv;1181const struct bin_test_param *param = test->param_value;1182unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1183u32 packed_payload[3], unpacked_payload[2], readback[3];1184unsigned int alg_base_words, packed_patch_pos_words;1185unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1186unsigned int reg_addr;1187struct firmware *fw;11881189static_assert(sizeof(readback) == sizeof(packed_payload));1190static_assert(sizeof(readback) >= sizeof(unpacked_payload));11911192get_random_bytes(packed_payload, sizeof(packed_payload));1193get_random_bytes(unpacked_payload, sizeof(unpacked_payload));11941195alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1196bin_test_mock_algs[param->alg_idx].id,1197param->mem_type);1198alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);11991200/* Round packed start word up to a packed boundary and move to the next boundary */1201packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;12021203/* Patch the leading unpacked words */1204param->add_patch(priv->local->bin_builder,1205bin_test_mock_algs[param->alg_idx].id,1206bin_test_mock_algs[param->alg_idx].ver,1207unpacked_mem_type,1208((packed_patch_pos_words - 2) - alg_base_words) * 4,1209&unpacked_payload[0], sizeof(unpacked_payload[0]));1210param->add_patch(priv->local->bin_builder,1211bin_test_mock_algs[param->alg_idx].id,1212bin_test_mock_algs[param->alg_idx].ver,1213unpacked_mem_type,1214((packed_patch_pos_words - 1) - alg_base_words) * 4,1215&unpacked_payload[1], sizeof(unpacked_payload[1]));1216/* ... then the packed block */1217patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1218param->add_patch(priv->local->bin_builder,1219bin_test_mock_algs[param->alg_idx].id,1220bin_test_mock_algs[param->alg_idx].ver,1221param->mem_type,1222(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1223&packed_payload, sizeof(packed_payload));12241225fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1226KUNIT_ASSERT_EQ(test,1227cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1228fw, "mock_bin", "misc"),12290);12301231/* Content of packed registers should match packed_payload */1232reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1233(patch_pos_in_packed_regs * 4);1234memset(readback, 0, sizeof(readback));1235KUNIT_EXPECT_EQ(test,1236regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),12370);1238KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));12391240/* Drop expected writes from the cache */1241cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));12421243/* Content of unpacked registers should match unpacked_payload */1244reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1245(packed_patch_pos_words - 2) * 4;1246memset(readback, 0, sizeof(readback));1247KUNIT_EXPECT_EQ(test,1248regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1249sizeof(unpacked_payload)),12500);1251KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));12521253/* Drop expected writes from the cache */1254cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));12551256/* Drop expected writes and the cache should then be clean */1257cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1258KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1259}12601261/*1262* Patch data that starts two words before a packed boundary using one1263* block of two unpacked words followed by one packed block.1264*/1265static void bin_patch_2_leading_1_packed(struct kunit *test)1266{1267struct cs_dsp_test *priv = test->priv;1268const struct bin_test_param *param = test->param_value;1269unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1270u32 packed_payload[3], unpacked_payload[2], readback[3];1271unsigned int alg_base_words, packed_patch_pos_words;1272unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1273unsigned int reg_addr;1274struct firmware *fw;12751276static_assert(sizeof(readback) == sizeof(packed_payload));1277static_assert(sizeof(readback) >= sizeof(unpacked_payload));12781279get_random_bytes(packed_payload, sizeof(packed_payload));1280get_random_bytes(unpacked_payload, sizeof(unpacked_payload));12811282alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1283bin_test_mock_algs[param->alg_idx].id,1284param->mem_type);1285alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);12861287/* Round packed start word up to a packed boundary and move to the next boundary */1288packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;12891290/* Patch the leading unpacked words */1291param->add_patch(priv->local->bin_builder,1292bin_test_mock_algs[param->alg_idx].id,1293bin_test_mock_algs[param->alg_idx].ver,1294unpacked_mem_type,1295((packed_patch_pos_words - 2) - alg_base_words) * 4,1296unpacked_payload, sizeof(unpacked_payload));1297/* ... then the packed block */1298patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1299param->add_patch(priv->local->bin_builder,1300bin_test_mock_algs[param->alg_idx].id,1301bin_test_mock_algs[param->alg_idx].ver,1302param->mem_type,1303(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1304&packed_payload, sizeof(packed_payload));13051306fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1307KUNIT_ASSERT_EQ(test,1308cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1309fw, "mock_bin", "misc"),13100);13111312/* Content of packed registers should match packed_payload */1313reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1314(patch_pos_in_packed_regs * 4);1315memset(readback, 0, sizeof(readback));1316KUNIT_EXPECT_EQ(test,1317regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),13180);1319KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));13201321/* Drop expected writes from the cache */1322cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));13231324/* Content of unpacked registers should match unpacked_payload */1325reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1326(packed_patch_pos_words - 2) * 4;1327memset(readback, 0, sizeof(readback));1328KUNIT_EXPECT_EQ(test,1329regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1330sizeof(unpacked_payload)),13310);1332KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));13331334/* Drop expected writes from the cache */1335cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));13361337/* Drop expected writes and the cache should then be clean */1338cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1339KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1340}13411342/*1343* Patch data that starts three words before a packed boundary using three1344* unpacked words followed by one packed block.1345*/1346static void bin_patch_3_single_leading_1_packed(struct kunit *test)1347{1348struct cs_dsp_test *priv = test->priv;1349const struct bin_test_param *param = test->param_value;1350unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1351u32 packed_payload[3], unpacked_payload[3], readback[3];1352unsigned int alg_base_words, packed_patch_pos_words;1353unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1354unsigned int reg_addr;1355struct firmware *fw;13561357static_assert(sizeof(readback) == sizeof(packed_payload));1358static_assert(sizeof(readback) >= sizeof(unpacked_payload));13591360get_random_bytes(packed_payload, sizeof(packed_payload));1361get_random_bytes(unpacked_payload, sizeof(unpacked_payload));13621363alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1364bin_test_mock_algs[param->alg_idx].id,1365param->mem_type);1366alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);13671368/* Round packed start word up to a packed boundary and move to the next boundary */1369packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;13701371/* Patch the leading unpacked words */1372param->add_patch(priv->local->bin_builder,1373bin_test_mock_algs[param->alg_idx].id,1374bin_test_mock_algs[param->alg_idx].ver,1375unpacked_mem_type,1376((packed_patch_pos_words - 3) - alg_base_words) * 4,1377&unpacked_payload[0], sizeof(unpacked_payload[0]));1378param->add_patch(priv->local->bin_builder,1379bin_test_mock_algs[param->alg_idx].id,1380bin_test_mock_algs[param->alg_idx].ver,1381unpacked_mem_type,1382((packed_patch_pos_words - 2) - alg_base_words) * 4,1383&unpacked_payload[1], sizeof(unpacked_payload[1]));1384param->add_patch(priv->local->bin_builder,1385bin_test_mock_algs[param->alg_idx].id,1386bin_test_mock_algs[param->alg_idx].ver,1387unpacked_mem_type,1388((packed_patch_pos_words - 1) - alg_base_words) * 4,1389&unpacked_payload[2], sizeof(unpacked_payload[2]));1390/* ... then the packed block */1391patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1392param->add_patch(priv->local->bin_builder,1393bin_test_mock_algs[param->alg_idx].id,1394bin_test_mock_algs[param->alg_idx].ver,1395param->mem_type,1396(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1397&packed_payload, sizeof(packed_payload));13981399fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1400KUNIT_ASSERT_EQ(test,1401cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1402fw, "mock_bin", "misc"),14030);14041405/* Content of packed registers should match packed_payload */1406reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1407(patch_pos_in_packed_regs * 4);1408memset(readback, 0, sizeof(readback));1409KUNIT_EXPECT_EQ(test,1410regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),14110);1412KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));14131414/* Drop expected writes from the cache */1415cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));14161417/* Content of unpacked registers should match unpacked_payload */1418reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1419(packed_patch_pos_words - 3) * 4;1420memset(readback, 0, sizeof(readback));1421KUNIT_EXPECT_EQ(test,1422regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1423sizeof(unpacked_payload)),14240);1425KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));14261427/* Drop expected writes from the cache */1428cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));14291430/* Drop expected writes and the cache should then be clean */1431cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1432KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1433}14341435/*1436* Patch data that starts three words before a packed boundary using one1437* block of three unpacked words followed by one packed block.1438*/1439static void bin_patch_3_leading_1_packed(struct kunit *test)1440{1441struct cs_dsp_test *priv = test->priv;1442const struct bin_test_param *param = test->param_value;1443unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1444u32 packed_payload[3], unpacked_payload[3], readback[3];1445unsigned int alg_base_words, packed_patch_pos_words;1446unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1447unsigned int reg_addr;1448struct firmware *fw;14491450static_assert(sizeof(readback) == sizeof(packed_payload));1451static_assert(sizeof(readback) >= sizeof(unpacked_payload));14521453get_random_bytes(packed_payload, sizeof(packed_payload));1454get_random_bytes(unpacked_payload, sizeof(unpacked_payload));14551456alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1457bin_test_mock_algs[param->alg_idx].id,1458param->mem_type);1459alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);14601461/* Round packed start word up to a packed boundary and move to the next boundary */1462packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;14631464/* Patch the leading unpacked words */1465param->add_patch(priv->local->bin_builder,1466bin_test_mock_algs[param->alg_idx].id,1467bin_test_mock_algs[param->alg_idx].ver,1468unpacked_mem_type,1469((packed_patch_pos_words - 3) - alg_base_words) * 4,1470unpacked_payload, sizeof(unpacked_payload));1471/* ... then the packed block */1472patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1473param->add_patch(priv->local->bin_builder,1474bin_test_mock_algs[param->alg_idx].id,1475bin_test_mock_algs[param->alg_idx].ver,1476param->mem_type,1477(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1478&packed_payload, sizeof(packed_payload));14791480fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1481KUNIT_ASSERT_EQ(test,1482cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1483fw, "mock_bin", "misc"),14840);14851486/* Content of packed registers should match packed_payload */1487reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1488(patch_pos_in_packed_regs * 4);1489memset(readback, 0, sizeof(readback));1490KUNIT_EXPECT_EQ(test,1491regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),14920);1493KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));14941495/* Drop expected writes from the cache */1496cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));14971498/* Content of unpacked registers should match unpacked_payload */1499reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1500(packed_patch_pos_words - 3) * 4;1501memset(readback, 0, sizeof(readback));1502KUNIT_EXPECT_EQ(test,1503regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1504sizeof(unpacked_payload)),15050);1506KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));15071508/* Drop expected writes from the cache */1509cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));15101511/* Drop expected writes and the cache should then be clean */1512cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1513KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1514}15151516/* bin file with a multiple payloads that each patch one packed block. */1517static void bin_patch_multi_onepacked(struct kunit *test)1518{1519struct cs_dsp_test *priv = test->priv;1520const struct bin_test_param *param = test->param_value;1521u32 packed_payloads[8][3], readback[8][3];1522unsigned int alg_base_words, patch_pos_words;1523unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1524unsigned int payload_offset;1525unsigned int reg_addr;1526struct firmware *fw;1527int i;15281529static_assert(sizeof(readback) == sizeof(packed_payloads));15301531get_random_bytes(packed_payloads, sizeof(packed_payloads));15321533alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1534bin_test_mock_algs[param->alg_idx].id,1535param->mem_type);1536alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);15371538/* Round patch start word up to a packed boundary */1539patch_pos_words = round_up(alg_base_words + param->offset_words, 4);15401541/* Add one payload per packed block */1542for (i = 0; i < ARRAY_SIZE(packed_payloads); ++i) {1543patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words + (i * 4));1544payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1545param->add_patch(priv->local->bin_builder,1546bin_test_mock_algs[param->alg_idx].id,1547bin_test_mock_algs[param->alg_idx].ver,1548param->mem_type,1549payload_offset,1550&packed_payloads[i], sizeof(packed_payloads[i]));1551}15521553fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1554KUNIT_ASSERT_EQ(test,1555cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1556fw, "mock_bin", "misc"),15570);15581559/* Content of packed registers should match packed_payloads */1560patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1561reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1562(patch_pos_in_packed_regs * 4);1563memset(readback, 0, sizeof(readback));1564KUNIT_EXPECT_EQ(test,1565regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),15660);1567KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));15681569/* Drop expected writes and the cache should then be clean */1570cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1571cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));1572KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1573}15741575/*1576* bin file with a multiple payloads that each patch one packed block.1577* The payloads are not in address order.1578*/1579static void bin_patch_multi_onepacked_unordered(struct kunit *test)1580{1581struct cs_dsp_test *priv = test->priv;1582const struct bin_test_param *param = test->param_value;1583static const u8 payload_order[] = { 4, 3, 6, 1, 0, 7, 5, 2 };1584u32 packed_payloads[8][3], readback[8][3];1585unsigned int alg_base_words, patch_pos_words;1586unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1587unsigned int payload_offset;1588unsigned int reg_addr;1589struct firmware *fw;1590int i;15911592static_assert(ARRAY_SIZE(payload_order) == ARRAY_SIZE(packed_payloads));1593static_assert(sizeof(readback) == sizeof(packed_payloads));15941595get_random_bytes(packed_payloads, sizeof(packed_payloads));15961597alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1598bin_test_mock_algs[param->alg_idx].id,1599param->mem_type);1600alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);16011602/* Round patch start word up to a packed boundary */1603patch_pos_words = round_up(alg_base_words + param->offset_words, 4);16041605/* Add one payload per packed block */1606for (i = 0; i < ARRAY_SIZE(payload_order); ++i) {1607patch_pos_in_packed_regs =1608_num_words_to_num_packed_regs(patch_pos_words + (payload_order[i] * 4));1609payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1610param->add_patch(priv->local->bin_builder,1611bin_test_mock_algs[param->alg_idx].id,1612bin_test_mock_algs[param->alg_idx].ver,1613param->mem_type,1614payload_offset,1615&packed_payloads[payload_order[i]],1616sizeof(packed_payloads[0]));1617}16181619fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1620KUNIT_ASSERT_EQ(test,1621cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1622fw, "mock_bin", "misc"),16230);16241625/* Content in registers should match the order of data in packed_payloads */1626patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1627reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1628(patch_pos_in_packed_regs * 4);1629memset(readback, 0, sizeof(readback));1630KUNIT_EXPECT_EQ(test,1631regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),16320);1633KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));16341635/* Drop expected writes and the cache should then be clean */1636cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1637cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));1638KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1639}16401641/*1642* bin file with a multiple payloads that each patch one packed block.1643* The payloads are not in address order. The patched memory is not contiguous.1644*/1645static void bin_patch_multi_onepacked_sparse_unordered(struct kunit *test)1646{1647struct cs_dsp_test *priv = test->priv;1648const struct bin_test_param *param = test->param_value;1649static const u8 word_offsets[] = { 60, 24, 76, 4, 40, 52, 48, 36, 12 };1650u32 packed_payloads[9][3], readback[3];1651unsigned int alg_base_words, alg_base_in_packed_regs;1652unsigned int patch_pos_words, patch_pos_in_packed_regs, payload_offset;1653unsigned int reg_addr;1654struct firmware *fw;1655int i;16561657static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(packed_payloads));1658static_assert(sizeof(readback) == sizeof(packed_payloads[0]));16591660get_random_bytes(packed_payloads, sizeof(packed_payloads));16611662alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1663bin_test_mock_algs[param->alg_idx].id,1664param->mem_type);1665alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);16661667/* Add one payload per packed block */1668for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {1669/* Round patch start word up to a packed boundary */1670patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);1671patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1672payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1673param->add_patch(priv->local->bin_builder,1674bin_test_mock_algs[param->alg_idx].id,1675bin_test_mock_algs[param->alg_idx].ver,1676param->mem_type,1677payload_offset,1678&packed_payloads[i],1679sizeof(packed_payloads[0]));1680}16811682fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1683KUNIT_ASSERT_EQ(test,1684cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1685fw, "mock_bin", "misc"),16860);16871688/* Content of packed registers should match packed_payloads */1689for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {1690patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);1691patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1692reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1693(patch_pos_in_packed_regs * 4);1694memset(readback, 0, sizeof(readback));1695KUNIT_EXPECT_EQ(test,1696regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1697sizeof(readback)),16980);1699KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads[i], sizeof(packed_payloads[i]));17001701/* Drop expected writes from the cache */1702cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads[i]));1703}17041705/* Drop expected writes and the cache should then be clean */1706cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1707KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1708}17091710/*1711* bin file that patches a single packed block in each of the memory regions1712* of one algorithm.1713*/1714static void bin_patch_1_packed_multiple_mems(struct kunit *test)1715{1716struct cs_dsp_test *priv = test->priv;1717const struct bin_test_param *param = test->param_value;1718u32 packed_xm_payload[3], packed_ym_payload[3], readback[3];1719unsigned int alg_xm_base_words, alg_ym_base_words;1720unsigned int xm_patch_pos_words, ym_patch_pos_words;1721unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1722unsigned int reg_addr;1723struct firmware *fw;17241725static_assert(sizeof(readback) == sizeof(packed_xm_payload));1726static_assert(sizeof(readback) == sizeof(packed_ym_payload));17271728get_random_bytes(packed_xm_payload, sizeof(packed_xm_payload));1729get_random_bytes(packed_ym_payload, sizeof(packed_ym_payload));17301731alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1732bin_test_mock_algs[param->alg_idx].id,1733WMFW_HALO_XM_PACKED);1734alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1735bin_test_mock_algs[param->alg_idx].id,1736WMFW_HALO_YM_PACKED);17371738/* Round patch start word up to a packed boundary */1739xm_patch_pos_words = round_up(alg_xm_base_words + param->offset_words, 4);1740ym_patch_pos_words = round_up(alg_ym_base_words + param->offset_words, 4);17411742/* Add XM and YM patches */1743alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_xm_base_words);1744patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);1745param->add_patch(priv->local->bin_builder,1746bin_test_mock_algs[param->alg_idx].id,1747bin_test_mock_algs[param->alg_idx].ver,1748WMFW_HALO_XM_PACKED,1749(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1750packed_xm_payload, sizeof(packed_xm_payload));17511752alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_ym_base_words);1753patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);1754param->add_patch(priv->local->bin_builder,1755bin_test_mock_algs[param->alg_idx].id,1756bin_test_mock_algs[param->alg_idx].ver,1757WMFW_HALO_YM_PACKED,1758(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1759packed_ym_payload, sizeof(packed_ym_payload));17601761fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1762KUNIT_ASSERT_EQ(test,1763cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1764fw, "mock_bin", "misc"),17650);17661767/* Content of packed XM registers should match packed_xm_payload */1768patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);1769reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_XM_PACKED) +1770(patch_pos_in_packed_regs * 4);1771memset(readback, 0, sizeof(readback));1772KUNIT_EXPECT_EQ(test,1773regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),17740);1775KUNIT_EXPECT_MEMEQ(test, readback, packed_xm_payload, sizeof(packed_xm_payload));17761777/* Drop expected writes from the cache */1778cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_xm_payload));17791780/* Content of packed YM registers should match packed_ym_payload */1781patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);1782reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_YM_PACKED) +1783(patch_pos_in_packed_regs * 4);1784memset(readback, 0, sizeof(readback));1785KUNIT_EXPECT_EQ(test,1786regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),17870);1788KUNIT_EXPECT_MEMEQ(test, readback, packed_ym_payload, sizeof(packed_ym_payload));17891790/* Drop expected writes from the cache */1791cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_ym_payload));17921793/* Drop expected writes and the cache should then be clean */1794cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1795KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1796}17971798/*1799* bin file that patches a single packed block in multiple algorithms.1800*/1801static void bin_patch_1_packed_multiple_algs(struct kunit *test)1802{1803struct cs_dsp_test *priv = test->priv;1804const struct bin_test_param *param = test->param_value;1805u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];1806u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];1807unsigned int alg_base_words, patch_pos_words;1808unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1809unsigned int reg_addr, payload_offset;1810struct firmware *fw;1811int i;18121813static_assert(sizeof(readback) == sizeof(packed_payload));18141815get_random_bytes(packed_payload, sizeof(packed_payload));18161817/* For each algorithm patch one DSP word to a value from packed_payload */1818for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {1819alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1820bin_test_mock_algs[i].id,1821param->mem_type);1822alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);18231824/* Round patch start word up to a packed boundary */1825patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1826patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);18271828payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1829param->add_patch(priv->local->bin_builder,1830bin_test_mock_algs[i].id,1831bin_test_mock_algs[i].ver,1832param->mem_type,1833payload_offset,1834packed_payload[i], sizeof(packed_payload[i]));1835}18361837fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1838KUNIT_ASSERT_EQ(test,1839cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1840fw, "mock_bin", "misc"),18410);18421843memset(readback, 0, sizeof(readback));18441845/*1846* Readback the registers that should have been written. Place1847* the values into the expected location in readback[] so that1848* the content of readback[] should match packed_payload[]1849*/1850for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {1851alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1852bin_test_mock_algs[i].id,1853param->mem_type);1854alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);18551856patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1857patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);18581859reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1860(patch_pos_in_packed_regs * 4);1861KUNIT_EXPECT_EQ(test,1862regmap_raw_read(priv->dsp->regmap, reg_addr,1863readback[i], sizeof(readback[i])),18640);18651866/* Drop expected writes from the cache */1867cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));1868}18691870KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));18711872/* Drop expected writes and the cache should then be clean */1873cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1874KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1875}18761877/*1878* bin file that patches a single packed block in multiple algorithms.1879* The algorithms are not patched in the same order they appear in the XM header.1880*/1881static void bin_patch_1_packed_multiple_algs_unordered(struct kunit *test)1882{1883struct cs_dsp_test *priv = test->priv;1884const struct bin_test_param *param = test->param_value;1885static const u8 alg_order[] = { 3, 0, 2, 1 };1886u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];1887u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];1888unsigned int alg_base_words, patch_pos_words;1889unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1890unsigned int reg_addr, payload_offset;1891struct firmware *fw;1892int i, alg_idx;18931894static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));1895static_assert(sizeof(readback) == sizeof(packed_payload));18961897get_random_bytes(packed_payload, sizeof(packed_payload));18981899/*1900* For each algorithm index in alg_order[] patch one DSP word in1901* that algorithm to a value from packed_payload.1902*/1903for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {1904alg_idx = alg_order[i];1905alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1906bin_test_mock_algs[alg_idx].id,1907param->mem_type);1908alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);19091910/* Round patch start word up to a packed boundary */1911patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1912patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);19131914payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1915param->add_patch(priv->local->bin_builder,1916bin_test_mock_algs[alg_idx].id,1917bin_test_mock_algs[alg_idx].ver,1918param->mem_type,1919payload_offset,1920packed_payload[i], sizeof(packed_payload[i]));1921}19221923fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1924KUNIT_ASSERT_EQ(test,1925cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1926fw, "mock_bin", "misc"),19270);19281929memset(readback, 0, sizeof(readback));19301931/*1932* Readback the registers that should have been written. Place1933* the values into the expected location in readback[] so that1934* the content of readback[] should match packed_payload[]1935*/1936for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {1937alg_idx = alg_order[i];1938alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1939bin_test_mock_algs[alg_idx].id,1940param->mem_type);19411942patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1943patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);19441945reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1946(patch_pos_in_packed_regs * 4);1947KUNIT_EXPECT_EQ(test,1948regmap_raw_read(priv->dsp->regmap, reg_addr,1949readback[i], sizeof(readback[i])),19500);19511952/* Drop expected writes from the cache */1953cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));1954}19551956KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));19571958/* Drop expected writes and the cache should then be clean */1959cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1960KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1961}19621963/*1964* bin file that contains a mix of packed and unpacked words.1965* payloads are in random offset order. Offsets that are on a packed boundary1966* are written as a packed block. Offsets that are not on a packed boundary1967* are written as a single unpacked word.1968*/1969static void bin_patch_mixed_packed_unpacked_random(struct kunit *test)1970{1971struct cs_dsp_test *priv = test->priv;1972const struct bin_test_param *param = test->param_value;1973static const u8 offset_words[] = {197458, 68, 50, 10, 44, 17, 74, 36, 8, 7, 49, 11, 78, 57, 65, 2,197548, 38, 22, 70, 77, 21, 61, 56, 75, 34, 27, 3, 31, 20, 43, 63,19765, 30, 32, 25, 33, 79, 29, 0, 37, 60, 69, 52, 13, 12, 24, 26,19774, 51, 76, 72, 16, 6, 39, 62, 15, 41, 28, 73, 53, 40, 45, 54,197814, 55, 46, 66, 64, 59, 23, 9, 67, 47, 19, 71, 35, 18, 42, 1,1979};1980struct {1981u32 packed[80][3];1982u32 unpacked[80];1983} *payload;1984u32 readback[3];1985unsigned int alg_base_words, patch_pos_words;1986unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1987unsigned int reg_addr, payload_offset;1988int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1989struct firmware *fw;1990int i;19911992payload = kunit_kmalloc(test, sizeof(*payload), GFP_KERNEL);1993KUNIT_ASSERT_NOT_NULL(test, payload);19941995get_random_bytes(payload->packed, sizeof(payload->packed));1996get_random_bytes(payload->unpacked, sizeof(payload->unpacked));19971998/* Create a patch entry for every offset in offset_words[] */1999for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {2000alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2001bin_test_mock_algs[0].id,2002param->mem_type);2003/*2004* If the offset is on a packed boundary use a packed payload else2005* use an unpacked word2006*/2007patch_pos_words = alg_base_words + offset_words[i];2008if ((patch_pos_words % 4) == 0) {2009alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);2010patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);2011payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;2012param->add_patch(priv->local->bin_builder,2013bin_test_mock_algs[0].id,2014bin_test_mock_algs[0].ver,2015param->mem_type,2016payload_offset,2017payload->packed[i],2018sizeof(payload->packed[i]));2019} else {2020payload_offset = offset_words[i] * 4;2021param->add_patch(priv->local->bin_builder,2022bin_test_mock_algs[0].id,2023bin_test_mock_algs[0].ver,2024unpacked_mem_type,2025payload_offset,2026&payload->unpacked[i],2027sizeof(payload->unpacked[i]));2028}2029}20302031fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);2032KUNIT_ASSERT_EQ(test,2033cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",2034fw, "mock_bin", "misc"),20350);20362037/*2038* Readback the packed registers that should have been written.2039* Place the values into the expected location in readback[] so2040* that the content of readback[] should match payload->packed[]2041*/2042for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {2043alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2044bin_test_mock_algs[0].id,2045param->mem_type);2046patch_pos_words = alg_base_words + offset_words[i];20472048/* Skip if the offset is not on a packed boundary */2049if ((patch_pos_words % 4) != 0)2050continue;20512052patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);20532054reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +2055(patch_pos_in_packed_regs * 4);20562057memset(readback, 0, sizeof(readback));2058KUNIT_EXPECT_EQ(test,2059regmap_raw_read(priv->dsp->regmap, reg_addr, readback,2060sizeof(readback)),20610);2062KUNIT_EXPECT_MEMEQ(test, readback, payload->packed[i], sizeof(payload->packed[i]));20632064/* Drop expected writes from the cache */2065cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->packed[i]));2066}20672068/*2069* Readback the unpacked registers that should have been written.2070* Place the values into the expected location in readback[] so2071* that the content of readback[] should match payload->unpacked[]2072*/2073for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {2074alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2075bin_test_mock_algs[0].id,2076unpacked_mem_type);20772078patch_pos_words = alg_base_words + offset_words[i];20792080/* Skip if the offset is on a packed boundary */2081if ((patch_pos_words % 4) == 0)2082continue;20832084reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +2085((patch_pos_words) * 4);20862087readback[0] = 0;2088KUNIT_EXPECT_EQ(test,2089regmap_raw_read(priv->dsp->regmap, reg_addr,2090&readback[0], sizeof(readback[0])),20910);2092KUNIT_EXPECT_EQ(test, readback[0], payload->unpacked[i]);20932094/* Drop expected writes from the cache */2095cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->unpacked[i]));2096}20972098/* Drop expected writes and the cache should then be clean */2099cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);2100KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));2101}21022103/* Bin file with name and multiple info blocks */2104static void bin_patch_name_and_info(struct kunit *test)2105{2106struct cs_dsp_test *priv = test->priv;2107unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);2108u32 reg_val, payload_data;2109char *infobuf;2110unsigned int alg_base_words, reg_addr;2111struct firmware *fw;21122113get_random_bytes(&payload_data, sizeof(payload_data));21142115alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2116bin_test_mock_algs[0].id,2117WMFW_ADSP2_YM);21182119/* Add a name block and info block */2120cs_dsp_mock_bin_add_name(priv->local->bin_builder, "The name");2121cs_dsp_mock_bin_add_info(priv->local->bin_builder, "Some info");21222123/* Add a big block of info */2124infobuf = kunit_kzalloc(test, 512, GFP_KERNEL);2125KUNIT_ASSERT_NOT_ERR_OR_NULL(test, infobuf);21262127for (; strlcat(infobuf, "Waffle{Blah}\n", 512) < 512; )2128;21292130cs_dsp_mock_bin_add_info(priv->local->bin_builder, infobuf);21312132/* Add a patch */2133cs_dsp_mock_bin_add_patch(priv->local->bin_builder,2134bin_test_mock_algs[0].id,2135bin_test_mock_algs[0].ver,2136WMFW_ADSP2_YM,21370,2138&payload_data, sizeof(payload_data));21392140fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);2141KUNIT_ASSERT_EQ(test,2142cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",2143fw, "mock_bin", "misc"),21440);21452146/* Content of registers should match payload_data */2147reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);2148reg_addr += alg_base_words * reg_inc_per_word;2149reg_val = 0;2150KUNIT_EXPECT_EQ(test,2151regmap_raw_read(priv->dsp->regmap, reg_addr,2152®_val, sizeof(reg_val)),21530);2154KUNIT_EXPECT_EQ(test, reg_val, payload_data);2155}21562157static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp,2158int wmdr_ver)2159{2160struct cs_dsp_test *priv;2161struct cs_dsp_mock_xm_header *xm_hdr;2162struct device *test_dev;2163int ret;21642165priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);2166if (!priv)2167return -ENOMEM;21682169priv->local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);2170if (!priv->local)2171return -ENOMEM;21722173priv->test = test;2174priv->dsp = dsp;2175test->priv = priv;21762177/* Create dummy struct device */2178test_dev = kunit_device_register(test, "cs_dsp_test_drv");2179if (IS_ERR(test_dev))2180return PTR_ERR(test_dev);21812182dsp->dev = get_device(test_dev);2183if (!dsp->dev)2184return -ENODEV;21852186ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);2187if (ret)2188return ret;21892190dev_set_drvdata(dsp->dev, priv);21912192/* Allocate regmap */2193ret = cs_dsp_mock_regmap_init(priv);2194if (ret)2195return ret;21962197/* Create an XM header */2198xm_hdr = cs_dsp_create_mock_xm_header(priv,2199bin_test_mock_algs,2200ARRAY_SIZE(bin_test_mock_algs));2201KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_hdr);2202ret = cs_dsp_mock_xm_header_write_to_regmap(xm_hdr);2203KUNIT_ASSERT_EQ(test, ret, 0);22042205priv->local->bin_builder =2206cs_dsp_mock_bin_init(priv, wmdr_ver,2207cs_dsp_mock_xm_header_get_fw_version(xm_hdr));2208KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->local->bin_builder);22092210/* We must provide a dummy wmfw to load */2211priv->local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, -1);2212priv->local->wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);22132214dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);2215KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);22162217switch (dsp->type) {2218case WMFW_ADSP2:2219ret = cs_dsp_adsp2_init(dsp);2220break;2221case WMFW_HALO:2222ret = cs_dsp_halo_init(dsp);2223break;2224default:2225KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);2226return -EINVAL;2227}22282229if (ret)2230return ret;22312232/* Automatically call cs_dsp_remove() when test case ends */2233ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);2234if (ret)2235return ret;22362237/*2238* The large number of test cases will cause an unusually large amount2239* of dev_info() messages from cs_dsp, so suppress these.2240*/2241cs_dsp_suppress_info_messages = true;22422243return 0;2244}22452246static void cs_dsp_bin_test_exit(struct kunit *test)2247{2248cs_dsp_suppress_info_messages = false;2249}22502251static int cs_dsp_bin_test_halo_init_common(struct kunit *test, int wmdr_ver)2252{2253struct cs_dsp *dsp;22542255/* Fill in cs_dsp and initialize */2256dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);2257if (!dsp)2258return -ENOMEM;22592260dsp->num = 1;2261dsp->type = WMFW_HALO;2262dsp->mem = cs_dsp_mock_halo_dsp1_regions;2263dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);2264dsp->base = cs_dsp_mock_halo_core_base;2265dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;22662267return cs_dsp_bin_test_common_init(test, dsp, wmdr_ver);2268}22692270static int cs_dsp_bin_test_halo_init(struct kunit *test)2271{2272return cs_dsp_bin_test_halo_init_common(test, 1);2273}22742275static int cs_dsp_bin_test_halo_wmdr3_init(struct kunit *test)2276{2277return cs_dsp_bin_test_halo_init_common(test, 3);2278}22792280static int cs_dsp_bin_test_adsp2_32bit_init(struct kunit *test)2281{2282struct cs_dsp *dsp;22832284/* Fill in cs_dsp and initialize */2285dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);2286if (!dsp)2287return -ENOMEM;22882289dsp->num = 1;2290dsp->type = WMFW_ADSP2;2291dsp->rev = 1;2292dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;2293dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);2294dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;22952296return cs_dsp_bin_test_common_init(test, dsp, 1);2297}22982299static int cs_dsp_bin_test_adsp2_16bit_init(struct kunit *test)2300{2301struct cs_dsp *dsp;23022303/* Fill in cs_dsp and initialize */2304dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);2305if (!dsp)2306return -ENOMEM;23072308dsp->num = 1;2309dsp->type = WMFW_ADSP2;2310dsp->rev = 0;2311dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;2312dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);2313dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;23142315return cs_dsp_bin_test_common_init(test, dsp, 1);2316}23172318#define WMDR_PATCH_SHORT .add_patch = cs_dsp_mock_bin_add_patch2319#define WMDR_PATCH_LONG .add_patch = cs_dsp_mock_bin_add_patch_off3223202321/* Parameterize on choice of XM or YM with a range of word offsets */2322static const struct bin_test_param x_or_y_and_offset_param_cases[] = {2323{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0, WMDR_PATCH_SHORT },2324{ .mem_type = WMFW_ADSP2_XM, .offset_words = 1, WMDR_PATCH_SHORT },2325{ .mem_type = WMFW_ADSP2_XM, .offset_words = 2, WMDR_PATCH_SHORT },2326{ .mem_type = WMFW_ADSP2_XM, .offset_words = 3, WMDR_PATCH_SHORT },2327{ .mem_type = WMFW_ADSP2_XM, .offset_words = 4, WMDR_PATCH_SHORT },2328{ .mem_type = WMFW_ADSP2_XM, .offset_words = 23, WMDR_PATCH_SHORT },2329{ .mem_type = WMFW_ADSP2_XM, .offset_words = 22, WMDR_PATCH_SHORT },2330{ .mem_type = WMFW_ADSP2_XM, .offset_words = 21, WMDR_PATCH_SHORT },2331{ .mem_type = WMFW_ADSP2_XM, .offset_words = 20, WMDR_PATCH_SHORT },23322333{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0, WMDR_PATCH_SHORT },2334{ .mem_type = WMFW_ADSP2_YM, .offset_words = 1, WMDR_PATCH_SHORT },2335{ .mem_type = WMFW_ADSP2_YM, .offset_words = 2, WMDR_PATCH_SHORT },2336{ .mem_type = WMFW_ADSP2_YM, .offset_words = 3, WMDR_PATCH_SHORT },2337{ .mem_type = WMFW_ADSP2_YM, .offset_words = 4, WMDR_PATCH_SHORT },2338{ .mem_type = WMFW_ADSP2_YM, .offset_words = 23, WMDR_PATCH_SHORT },2339{ .mem_type = WMFW_ADSP2_YM, .offset_words = 22, WMDR_PATCH_SHORT },2340{ .mem_type = WMFW_ADSP2_YM, .offset_words = 21, WMDR_PATCH_SHORT },2341{ .mem_type = WMFW_ADSP2_YM, .offset_words = 20, WMDR_PATCH_SHORT },2342};23432344static const struct bin_test_param x_or_y_and_long_offset_param_cases[] = {2345/* Offset < 0xffff in long-offset block type */2346{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0, WMDR_PATCH_LONG },2347{ .mem_type = WMFW_ADSP2_XM, .offset_words = 1, WMDR_PATCH_LONG },2348{ .mem_type = WMFW_ADSP2_XM, .offset_words = 2, WMDR_PATCH_LONG },2349{ .mem_type = WMFW_ADSP2_XM, .offset_words = 3, WMDR_PATCH_LONG },2350{ .mem_type = WMFW_ADSP2_XM, .offset_words = 4, WMDR_PATCH_LONG },2351{ .mem_type = WMFW_ADSP2_XM, .offset_words = 23, WMDR_PATCH_LONG },2352{ .mem_type = WMFW_ADSP2_XM, .offset_words = 22, WMDR_PATCH_LONG },2353{ .mem_type = WMFW_ADSP2_XM, .offset_words = 21, WMDR_PATCH_LONG },2354{ .mem_type = WMFW_ADSP2_XM, .offset_words = 20, WMDR_PATCH_LONG },23552356/* Offset < 0xffff in long-offset block type */2357{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0, WMDR_PATCH_LONG },2358{ .mem_type = WMFW_ADSP2_YM, .offset_words = 1, WMDR_PATCH_LONG },2359{ .mem_type = WMFW_ADSP2_YM, .offset_words = 2, WMDR_PATCH_LONG },2360{ .mem_type = WMFW_ADSP2_YM, .offset_words = 3, WMDR_PATCH_LONG },2361{ .mem_type = WMFW_ADSP2_YM, .offset_words = 4, WMDR_PATCH_LONG },2362{ .mem_type = WMFW_ADSP2_YM, .offset_words = 23, WMDR_PATCH_LONG },2363{ .mem_type = WMFW_ADSP2_YM, .offset_words = 22, WMDR_PATCH_LONG },2364{ .mem_type = WMFW_ADSP2_YM, .offset_words = 21, WMDR_PATCH_LONG },2365{ .mem_type = WMFW_ADSP2_YM, .offset_words = 20, WMDR_PATCH_LONG },23662367/* Offset > 0xffff in long-offset block type */2368{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10000, WMDR_PATCH_LONG },2369{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10001, WMDR_PATCH_LONG },2370{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10002, WMDR_PATCH_LONG },2371{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10003, WMDR_PATCH_LONG },2372{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10004, WMDR_PATCH_LONG },2373{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f003, WMDR_PATCH_LONG },2374{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f002, WMDR_PATCH_LONG },2375{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f001, WMDR_PATCH_LONG },2376{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f000, WMDR_PATCH_LONG },23772378/* Offset > 0xffff in long-offset block type */2379{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10000, WMDR_PATCH_LONG },2380{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10001, WMDR_PATCH_LONG },2381{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10002, WMDR_PATCH_LONG },2382{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10003, WMDR_PATCH_LONG },2383{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10004, WMDR_PATCH_LONG },2384{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f003, WMDR_PATCH_LONG },2385{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f002, WMDR_PATCH_LONG },2386{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f001, WMDR_PATCH_LONG },2387{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f000, WMDR_PATCH_LONG },2388};23892390/* Parameterize on ZM with a range of word offsets */2391static const struct bin_test_param z_and_offset_param_cases[] = {2392{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 0, WMDR_PATCH_SHORT },2393{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 1, WMDR_PATCH_SHORT },2394{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 2, WMDR_PATCH_SHORT },2395{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 3, WMDR_PATCH_SHORT },2396{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 4, WMDR_PATCH_SHORT },2397{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 23, WMDR_PATCH_SHORT },2398{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 22, WMDR_PATCH_SHORT },2399{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 21, WMDR_PATCH_SHORT },2400{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 20, WMDR_PATCH_SHORT },2401};24022403/* Parameterize on choice of packed XM or YM with a range of word offsets */2404static const struct bin_test_param packed_x_or_y_and_offset_param_cases[] = {2405{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0, WMDR_PATCH_SHORT },2406{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 4, WMDR_PATCH_SHORT },2407{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 8, WMDR_PATCH_SHORT },2408{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 12, WMDR_PATCH_SHORT },24092410{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0, WMDR_PATCH_SHORT },2411{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 4, WMDR_PATCH_SHORT },2412{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 8, WMDR_PATCH_SHORT },2413{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 12, WMDR_PATCH_SHORT },2414};24152416static const struct bin_test_param packed_x_or_y_and_long_offset_param_cases[] = {2417/* Offset < 0xffff in long-offset block type */2418{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0, WMDR_PATCH_LONG },2419{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 4, WMDR_PATCH_LONG },2420{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 8, WMDR_PATCH_LONG },2421{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 12, WMDR_PATCH_LONG },24222423/* Offset < 0xffff in long-offset block type */2424{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0, WMDR_PATCH_LONG },2425{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 4, WMDR_PATCH_LONG },2426{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 8, WMDR_PATCH_LONG },2427{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 12, WMDR_PATCH_LONG },24282429/* Offset > 0xffff in long-offset block type */2430{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x10000, WMDR_PATCH_LONG },2431{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x10004, WMDR_PATCH_LONG },2432{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x10008, WMDR_PATCH_LONG },2433{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x2f000, WMDR_PATCH_LONG },2434{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x2f004, WMDR_PATCH_LONG },24352436/* Offset > 0xffff in long-offset block type */2437{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x10000, WMDR_PATCH_LONG },2438{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x10004, WMDR_PATCH_LONG },2439{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x10008, WMDR_PATCH_LONG },2440{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x2f000, WMDR_PATCH_LONG },2441{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x2f004, WMDR_PATCH_LONG },2442};24432444static void x_or_y_or_z_and_offset_param_desc(const struct bin_test_param *param,2445char *desc)2446{2447snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s@%u %s",2448cs_dsp_mem_region_name(param->mem_type),2449param->offset_words,2450(param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");2451}24522453KUNIT_ARRAY_PARAM(x_or_y_and_offset,2454x_or_y_and_offset_param_cases,2455x_or_y_or_z_and_offset_param_desc);24562457KUNIT_ARRAY_PARAM(x_or_y_and_long_offset,2458x_or_y_and_long_offset_param_cases,2459x_or_y_or_z_and_offset_param_desc);24602461KUNIT_ARRAY_PARAM(z_and_offset,2462z_and_offset_param_cases,2463x_or_y_or_z_and_offset_param_desc);24642465KUNIT_ARRAY_PARAM(packed_x_or_y_and_offset,2466packed_x_or_y_and_offset_param_cases,2467x_or_y_or_z_and_offset_param_desc);24682469KUNIT_ARRAY_PARAM(packed_x_or_y_and_long_offset,2470packed_x_or_y_and_long_offset_param_cases,2471x_or_y_or_z_and_offset_param_desc);24722473/* Parameterize on choice of packed XM or YM */2474static const struct bin_test_param packed_x_or_y_param_cases[] = {2475{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0, WMDR_PATCH_SHORT },2476{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0, WMDR_PATCH_SHORT },2477};24782479static const struct bin_test_param packed_x_or_y_long_param_cases[] = {2480{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0, WMDR_PATCH_LONG },2481{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0, WMDR_PATCH_LONG },2482};24832484static void x_or_y_or_z_param_desc(const struct bin_test_param *param,2485char *desc)2486{2487snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s %s",2488cs_dsp_mem_region_name(param->mem_type),2489(param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");2490}24912492KUNIT_ARRAY_PARAM(packed_x_or_y, packed_x_or_y_param_cases, x_or_y_or_z_param_desc);2493KUNIT_ARRAY_PARAM(packed_x_or_y_long, packed_x_or_y_long_param_cases, x_or_y_or_z_param_desc);24942495static const struct bin_test_param offset_param_cases[] = {2496{ .offset_words = 0, WMDR_PATCH_SHORT },2497{ .offset_words = 1, WMDR_PATCH_SHORT },2498{ .offset_words = 2, WMDR_PATCH_SHORT },2499{ .offset_words = 3, WMDR_PATCH_SHORT },2500{ .offset_words = 4, WMDR_PATCH_SHORT },2501{ .offset_words = 23, WMDR_PATCH_SHORT },2502{ .offset_words = 22, WMDR_PATCH_SHORT },2503{ .offset_words = 21, WMDR_PATCH_SHORT },2504{ .offset_words = 20, WMDR_PATCH_SHORT },2505};25062507static const struct bin_test_param long_offset_param_cases[] = {2508/* Offset < 0xffff in long-offset block type */2509{ .offset_words = 0, WMDR_PATCH_LONG },2510{ .offset_words = 1, WMDR_PATCH_LONG },2511{ .offset_words = 2, WMDR_PATCH_LONG },2512{ .offset_words = 3, WMDR_PATCH_LONG },2513{ .offset_words = 4, WMDR_PATCH_LONG },2514{ .offset_words = 23, WMDR_PATCH_LONG },2515{ .offset_words = 22, WMDR_PATCH_LONG },2516{ .offset_words = 21, WMDR_PATCH_LONG },2517{ .offset_words = 20, WMDR_PATCH_LONG },25182519/* Offset > 0xffff in long-offset block type */2520{ .offset_words = 0x10000, WMDR_PATCH_LONG },2521{ .offset_words = 0x10001, WMDR_PATCH_LONG },2522{ .offset_words = 0x10002, WMDR_PATCH_LONG },2523{ .offset_words = 0x10003, WMDR_PATCH_LONG },2524{ .offset_words = 0x10004, WMDR_PATCH_LONG },2525{ .offset_words = 0x2f000, WMDR_PATCH_LONG },2526{ .offset_words = 0x2f001, WMDR_PATCH_LONG },2527{ .offset_words = 0x2f002, WMDR_PATCH_LONG },2528{ .offset_words = 0x2f003, WMDR_PATCH_LONG },2529};25302531static void offset_param_desc(const struct bin_test_param *param, char *desc)2532{2533snprintf(desc, KUNIT_PARAM_DESC_SIZE, "@%u %s",2534param->offset_words,2535(param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");2536}25372538KUNIT_ARRAY_PARAM(offset, offset_param_cases, offset_param_desc);2539KUNIT_ARRAY_PARAM(long_offset, long_offset_param_cases, offset_param_desc);25402541static const struct bin_test_param alg_param_cases[] = {2542{ .alg_idx = 0, WMDR_PATCH_SHORT },2543{ .alg_idx = 1, WMDR_PATCH_SHORT },2544{ .alg_idx = 2, WMDR_PATCH_SHORT },2545{ .alg_idx = 3, WMDR_PATCH_SHORT },2546};25472548static const struct bin_test_param alg_long_param_cases[] = {2549{ .alg_idx = 0, WMDR_PATCH_LONG },2550{ .alg_idx = 1, WMDR_PATCH_LONG },2551{ .alg_idx = 2, WMDR_PATCH_LONG },2552{ .alg_idx = 3, WMDR_PATCH_LONG },2553};25542555static void alg_param_desc(const struct bin_test_param *param, char *desc)2556{2557WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));25582559snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg[%u] (%#x) %s",2560param->alg_idx, bin_test_mock_algs[param->alg_idx].id,2561(param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");2562}25632564KUNIT_ARRAY_PARAM(alg, alg_param_cases, alg_param_desc);2565KUNIT_ARRAY_PARAM(alg_long, alg_long_param_cases, alg_param_desc);25662567static const struct bin_test_param x_or_y_and_alg_param_cases[] = {2568{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 0, WMDR_PATCH_SHORT },2569{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 1, WMDR_PATCH_SHORT },2570{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 2, WMDR_PATCH_SHORT },2571{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 3, WMDR_PATCH_SHORT },25722573{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 0, WMDR_PATCH_SHORT },2574{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 1, WMDR_PATCH_SHORT },2575{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 2, WMDR_PATCH_SHORT },2576{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 3, WMDR_PATCH_SHORT },2577};25782579static const struct bin_test_param x_or_y_and_alg_long_param_cases[] = {2580{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 0, WMDR_PATCH_LONG },2581{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 1, WMDR_PATCH_LONG },2582{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 2, WMDR_PATCH_LONG },2583{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 3, WMDR_PATCH_LONG },25842585{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 0, WMDR_PATCH_LONG },2586{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 1, WMDR_PATCH_LONG },2587{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 2, WMDR_PATCH_LONG },2588{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 3, WMDR_PATCH_LONG },2589};25902591static void x_or_y_or_z_and_alg_param_desc(const struct bin_test_param *param, char *desc)2592{2593WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));25942595snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s alg[%u] (%#x) %s",2596cs_dsp_mem_region_name(param->mem_type),2597param->alg_idx, bin_test_mock_algs[param->alg_idx].id,2598(param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");2599}26002601KUNIT_ARRAY_PARAM(x_or_y_and_alg, x_or_y_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);2602KUNIT_ARRAY_PARAM(x_or_y_and_alg_long, x_or_y_and_alg_long_param_cases,2603x_or_y_or_z_and_alg_param_desc);26042605static const struct bin_test_param z_and_alg_param_cases[] = {2606{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 0, WMDR_PATCH_SHORT },2607{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 1, WMDR_PATCH_SHORT },2608{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 2, WMDR_PATCH_SHORT },2609{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 3, WMDR_PATCH_SHORT },2610};26112612KUNIT_ARRAY_PARAM(z_and_alg, z_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);26132614static const struct bin_test_param packed_x_or_y_and_alg_param_cases[] = {2615{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 0, WMDR_PATCH_SHORT },2616{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 1, WMDR_PATCH_SHORT },2617{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 2, WMDR_PATCH_SHORT },2618{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 3, WMDR_PATCH_SHORT },26192620{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 0, WMDR_PATCH_SHORT },2621{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 1, WMDR_PATCH_SHORT },2622{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 2, WMDR_PATCH_SHORT },2623{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 3, WMDR_PATCH_SHORT },2624};26252626static const struct bin_test_param packed_x_or_y_and_alg_long_param_cases[] = {2627{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 0, WMDR_PATCH_LONG },2628{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 1, WMDR_PATCH_LONG },2629{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 2, WMDR_PATCH_LONG },2630{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 3, WMDR_PATCH_LONG },26312632{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 0, WMDR_PATCH_LONG },2633{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 1, WMDR_PATCH_LONG },2634{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 2, WMDR_PATCH_LONG },2635{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 3, WMDR_PATCH_LONG },2636};26372638KUNIT_ARRAY_PARAM(packed_x_or_y_and_alg, packed_x_or_y_and_alg_param_cases,2639x_or_y_or_z_and_alg_param_desc);26402641KUNIT_ARRAY_PARAM(packed_x_or_y_and_alg_long, packed_x_or_y_and_alg_long_param_cases,2642x_or_y_or_z_and_alg_param_desc);26432644static struct kunit_case cs_dsp_bin_test_cases_halo[] = {2645/* Unpacked memory */2646KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),2647KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),2648KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),2649KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),2650KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),2651KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),2652KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),2653KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),2654KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),26552656/* Packed memory tests */2657KUNIT_CASE_PARAM(bin_patch_1_packed,2658packed_x_or_y_and_offset_gen_params),2659KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,2660packed_x_or_y_and_offset_gen_params),2661KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,2662packed_x_or_y_and_offset_gen_params),2663KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,2664packed_x_or_y_and_offset_gen_params),2665KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,2666packed_x_or_y_and_offset_gen_params),2667KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,2668packed_x_or_y_and_offset_gen_params),2669KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,2670packed_x_or_y_and_offset_gen_params),2671KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,2672packed_x_or_y_and_offset_gen_params),2673KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,2674packed_x_or_y_and_offset_gen_params),2675KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,2676packed_x_or_y_and_offset_gen_params),2677KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,2678packed_x_or_y_and_offset_gen_params),2679KUNIT_CASE_PARAM(bin_patch_multi_onepacked,2680packed_x_or_y_and_offset_gen_params),2681KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,2682packed_x_or_y_and_offset_gen_params),2683KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, offset_gen_params),2684KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_gen_params),2685KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,2686packed_x_or_y_and_alg_gen_params),2687KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,2688packed_x_or_y_and_offset_gen_params),2689KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,2690packed_x_or_y_and_offset_gen_params),2691KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,2692packed_x_or_y_gen_params),26932694KUNIT_CASE(bin_patch_name_and_info),26952696{ } /* terminator */2697};26982699static struct kunit_case cs_dsp_bin_test_cases_halo_wmdr3[] = {2700/* Unpacked memory */2701KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),2702KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),2703KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),2704KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),2705KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),2706KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),2707KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),2708KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),2709KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),27102711/* Packed memory tests */2712KUNIT_CASE_PARAM(bin_patch_1_packed,2713packed_x_or_y_and_offset_gen_params),2714KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,2715packed_x_or_y_and_offset_gen_params),2716KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,2717packed_x_or_y_and_offset_gen_params),2718KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,2719packed_x_or_y_and_offset_gen_params),2720KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,2721packed_x_or_y_and_offset_gen_params),2722KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,2723packed_x_or_y_and_offset_gen_params),2724KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,2725packed_x_or_y_and_offset_gen_params),2726KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,2727packed_x_or_y_and_offset_gen_params),2728KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,2729packed_x_or_y_and_offset_gen_params),2730KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,2731packed_x_or_y_and_offset_gen_params),2732KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,2733packed_x_or_y_and_offset_gen_params),2734KUNIT_CASE_PARAM(bin_patch_multi_onepacked,2735packed_x_or_y_and_offset_gen_params),2736KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,2737packed_x_or_y_and_offset_gen_params),2738KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, offset_gen_params),2739KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_gen_params),2740KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,2741packed_x_or_y_and_alg_gen_params),2742KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,2743packed_x_or_y_and_offset_gen_params),2744KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,2745packed_x_or_y_and_offset_gen_params),2746KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,2747packed_x_or_y_gen_params),27482749/* Unpacked memory with long-offset blocks */2750KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_long_offset_gen_params),2751KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_long_offset_gen_params),2752KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_long_offset_gen_params),2753KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_long_offset_gen_params),2754KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, long_offset_gen_params),2755KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_long_gen_params),2756KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_long_gen_params),2757KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_long_offset_gen_params),2758KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered,2759x_or_y_and_long_offset_gen_params),27602761/* Packed memory tests with long offset blocks */2762KUNIT_CASE_PARAM(bin_patch_1_packed,2763packed_x_or_y_and_long_offset_gen_params),2764KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,2765packed_x_or_y_and_long_offset_gen_params),2766KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,2767packed_x_or_y_and_long_offset_gen_params),2768KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,2769packed_x_or_y_and_long_offset_gen_params),2770KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,2771packed_x_or_y_and_long_offset_gen_params),2772KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,2773packed_x_or_y_and_long_offset_gen_params),2774KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,2775packed_x_or_y_and_long_offset_gen_params),2776KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,2777packed_x_or_y_and_long_offset_gen_params),2778KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,2779packed_x_or_y_and_long_offset_gen_params),2780KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,2781packed_x_or_y_and_long_offset_gen_params),2782KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,2783packed_x_or_y_and_long_offset_gen_params),2784KUNIT_CASE_PARAM(bin_patch_multi_onepacked,2785packed_x_or_y_and_long_offset_gen_params),2786KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,2787packed_x_or_y_and_long_offset_gen_params),2788KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, long_offset_gen_params),2789KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_long_gen_params),2790KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,2791packed_x_or_y_and_alg_long_gen_params),2792KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,2793packed_x_or_y_and_long_offset_gen_params),2794KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,2795packed_x_or_y_and_long_offset_gen_params),2796KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,2797packed_x_or_y_long_gen_params),27982799KUNIT_CASE(bin_patch_name_and_info),28002801{ } /* terminator */2802};28032804static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {2805/* XM and YM */2806KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),2807KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),2808KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),2809KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),2810KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),2811KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),2812KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),28132814/* ZM */2815KUNIT_CASE_PARAM(bin_patch_one_word, z_and_offset_gen_params),2816KUNIT_CASE_PARAM(bin_patch_one_multiword, z_and_offset_gen_params),2817KUNIT_CASE_PARAM(bin_patch_multi_oneword, z_and_offset_gen_params),2818KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, z_and_offset_gen_params),2819KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, z_and_alg_gen_params),2820KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, z_and_offset_gen_params),2821KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, z_and_offset_gen_params),28222823/* Other */2824KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),2825KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),28262827KUNIT_CASE(bin_patch_name_and_info),28282829{ } /* terminator */2830};28312832static struct kunit_suite cs_dsp_bin_test_halo = {2833.name = "cs_dsp_bin_halo",2834.init = cs_dsp_bin_test_halo_init,2835.exit = cs_dsp_bin_test_exit,2836.test_cases = cs_dsp_bin_test_cases_halo,2837};28382839static struct kunit_suite cs_dsp_bin_test_halo_wmdr3 = {2840.name = "cs_dsp_bin_halo_wmdr_v3",2841.init = cs_dsp_bin_test_halo_wmdr3_init,2842.test_cases = cs_dsp_bin_test_cases_halo_wmdr3,2843};28442845static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {2846.name = "cs_dsp_bin_adsp2_32bit",2847.init = cs_dsp_bin_test_adsp2_32bit_init,2848.exit = cs_dsp_bin_test_exit,2849.test_cases = cs_dsp_bin_test_cases_adsp2,2850};28512852static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {2853.name = "cs_dsp_bin_adsp2_16bit",2854.init = cs_dsp_bin_test_adsp2_16bit_init,2855.exit = cs_dsp_bin_test_exit,2856.test_cases = cs_dsp_bin_test_cases_adsp2,2857};28582859kunit_test_suites(&cs_dsp_bin_test_halo,2860&cs_dsp_bin_test_halo_wmdr3,2861&cs_dsp_bin_test_adsp2_32bit,2862&cs_dsp_bin_test_adsp2_16bit);286328642865