Path: blob/master/drivers/firmware/cirrus/test/cs_dsp_test_bin.c
26444 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/*20* Test method is:21*22* 1) Create a mock regmap in cache-only mode so that all writes will be cached.23* 2) Create a XM header with an algorithm list in the cached regmap.24* 3) Create dummy wmfw file to satisfy cs_dsp.25* 4) Create bin file content.26* 5) Call cs_dsp_power_up() with the bin file.27* 6) Readback the cached value of registers that should have been written and28* check they have the correct value.29* 7) All the registers that are expected to have been written are dropped from30* the cache (including the XM header). This should leave the cache clean.31* 8) If the cache is still dirty there have been unexpected writes.32*33* There are multiple different schemes used for addressing across34* ADSP2 and Halo Core DSPs:35*36* dsp words: The addressing scheme used by the DSP, pointers and lengths37* in DSP memory use this. A memory region (XM, YM, ZM) is38* also required to create a unique DSP memory address.39* registers: Addresses in the register map. Older ADSP2 devices have40* 16-bit registers with an address stride of 1. Newer ADSP241* devices have 32-bit registers with an address stride of 2.42* Halo Core devices have 32-bit registers with a stride of 4.43* unpacked: Registers that have a 1:1 mapping to DSP words44* packed: Registers that pack multiple DSP words more efficiently into45* multiple 32-bit registers. Because of this the relationship46* between a packed _register_ address and the corresponding47* _dsp word_ address is different from unpacked registers.48* Packed registers can only be accessed as a group of49* multiple registers, therefore can only read/write a group50* of multiple DSP words.51* Packed registers only exist on Halo Core DSPs.52*53* Addresses can also be relative to the start of an algorithm, and this54* can be expressed in dsp words, register addresses, or bytes.55*/5657KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)58KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)5960struct cs_dsp_test_local {61struct cs_dsp_mock_bin_builder *bin_builder;62struct cs_dsp_mock_wmfw_builder *wmfw_builder;63struct firmware *wmfw;64};6566struct bin_test_param {67const char *name;68int mem_type;69unsigned int offset_words;70int alg_idx;71};7273static const struct cs_dsp_mock_alg_def bin_test_mock_algs[] = {74{75.id = 0xfafa,76.ver = 0x100000,77.xm_size_words = 164,78.ym_size_words = 164,79.zm_size_words = 164,80},81{82.id = 0xfbfb,83.ver = 0x100000,84.xm_size_words = 99,85.ym_size_words = 99,86.zm_size_words = 99,87},88{89.id = 0xc321,90.ver = 0x100000,91.xm_size_words = 120,92.ym_size_words = 120,93.zm_size_words = 120,94},95{96.id = 0xb123,97.ver = 0x100000,98.xm_size_words = 96,99.ym_size_words = 96,100.zm_size_words = 96,101},102};103104/*105* Convert number of DSP words to number of packed registers rounded106* down to the nearest register.107* There are 3 registers for every 4 packed words.108*/109static unsigned int _num_words_to_num_packed_regs(unsigned int num_dsp_words)110{111return (num_dsp_words * 3) / 4;112}113114/* bin file that patches a single DSP word */115static void bin_patch_one_word(struct kunit *test)116{117struct cs_dsp_test *priv = test->priv;118const struct bin_test_param *param = test->param_value;119unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);120u32 reg_val, payload_data;121unsigned int alg_base_words, reg_addr;122struct firmware *fw;123124get_random_bytes(&payload_data, sizeof(payload_data));125126alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,127bin_test_mock_algs[param->alg_idx].id,128param->mem_type);129130cs_dsp_mock_bin_add_patch(priv->local->bin_builder,131bin_test_mock_algs[param->alg_idx].id,132bin_test_mock_algs[param->alg_idx].ver,133param->mem_type,134param->offset_words * reg_inc_per_word,135&payload_data, sizeof(payload_data));136137fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);138KUNIT_ASSERT_EQ(test,139cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",140fw, "mock_bin", "misc"),1410);142143/* Content of registers should match payload_data */144reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +145((alg_base_words + param->offset_words) * reg_inc_per_word);146reg_val = 0;147KUNIT_EXPECT_EQ(test,148regmap_raw_read(priv->dsp->regmap, reg_addr,149®_val, sizeof(reg_val)),1500);151KUNIT_EXPECT_EQ(test, reg_val, payload_data);152153/* Drop expected writes and the cache should then be clean */154cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);155cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);156157KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));158}159160/* bin file with a single payload that patches consecutive words */161static void bin_patch_one_multiword(struct kunit *test)162{163struct cs_dsp_test *priv = test->priv;164const struct bin_test_param *param = test->param_value;165unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);166u32 payload_data[16], readback[16];167unsigned int alg_base_words, reg_addr;168struct firmware *fw;169170static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));171172get_random_bytes(&payload_data, sizeof(payload_data));173memset(readback, 0, sizeof(readback));174175alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,176bin_test_mock_algs[param->alg_idx].id,177param->mem_type);178179cs_dsp_mock_bin_add_patch(priv->local->bin_builder,180bin_test_mock_algs[param->alg_idx].id,181bin_test_mock_algs[param->alg_idx].ver,182param->mem_type,183param->offset_words * reg_inc_per_word,184payload_data, sizeof(payload_data));185186fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);187KUNIT_ASSERT_EQ(test,188cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",189fw, "mock_bin", "misc"),1900);191192/* Content of registers should match payload_data */193reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +194((alg_base_words + param->offset_words) * reg_inc_per_word);195KUNIT_EXPECT_EQ(test,196regmap_raw_read(priv->dsp->regmap, reg_addr, readback,197sizeof(readback)),1980);199KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));200201/* Drop expected writes and the cache should then be clean */202cs_dsp_mock_regmap_drop_range(priv, reg_addr,203reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));204cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);205KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));206}207208/* bin file with a multiple one-word payloads that patch consecutive words */209static void bin_patch_multi_oneword(struct kunit *test)210{211struct cs_dsp_test *priv = test->priv;212const struct bin_test_param *param = test->param_value;213unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);214u32 payload_data[16], readback[16];215unsigned int alg_base_words, reg_addr;216struct firmware *fw;217int i;218219static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));220221get_random_bytes(&payload_data, sizeof(payload_data));222memset(readback, 0, sizeof(readback));223224alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,225bin_test_mock_algs[param->alg_idx].id,226param->mem_type);227228/* Add one payload per word */229for (i = 0; i < ARRAY_SIZE(payload_data); ++i) {230cs_dsp_mock_bin_add_patch(priv->local->bin_builder,231bin_test_mock_algs[param->alg_idx].id,232bin_test_mock_algs[param->alg_idx].ver,233param->mem_type,234(param->offset_words + i) * reg_inc_per_word,235&payload_data[i], sizeof(payload_data[i]));236}237238fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);239KUNIT_ASSERT_EQ(test,240cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",241fw, "mock_bin", "misc"),2420);243244/* Content of registers should match payload_data */245reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +246((alg_base_words + param->offset_words) * reg_inc_per_word);247KUNIT_EXPECT_EQ(test,248regmap_raw_read(priv->dsp->regmap, reg_addr, readback,249sizeof(readback)),2500);251KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));252253/* Drop expected writes and the cache should then be clean */254cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);255cs_dsp_mock_regmap_drop_range(priv, reg_addr,256reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));257KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));258}259260/*261* bin file with a multiple one-word payloads that patch a block of consecutive262* words but the payloads are not in address order.263*/264static void bin_patch_multi_oneword_unordered(struct kunit *test)265{266struct cs_dsp_test *priv = test->priv;267const struct bin_test_param *param = test->param_value;268unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);269u32 payload_data[16], readback[16];270static const u8 word_order[] = { 10, 2, 12, 4, 0, 11, 6, 1, 3, 15, 5, 13, 8, 7, 9, 14 };271unsigned int alg_base_words, reg_addr;272struct firmware *fw;273int i;274275static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));276static_assert(ARRAY_SIZE(word_order) == ARRAY_SIZE(payload_data));277278get_random_bytes(&payload_data, sizeof(payload_data));279memset(readback, 0, sizeof(readback));280281alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,282bin_test_mock_algs[param->alg_idx].id,283param->mem_type);284285/* Add one payload per word */286for (i = 0; i < ARRAY_SIZE(word_order); ++i) {287cs_dsp_mock_bin_add_patch(priv->local->bin_builder,288bin_test_mock_algs[param->alg_idx].id,289bin_test_mock_algs[param->alg_idx].ver,290param->mem_type,291(param->offset_words + word_order[i]) *292reg_inc_per_word,293&payload_data[word_order[i]], sizeof(payload_data[0]));294}295296fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);297KUNIT_ASSERT_EQ(test,298cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",299fw, "mock_bin", "misc"),3000);301302/* Content of registers should match payload_data */303reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +304((alg_base_words + param->offset_words) * reg_inc_per_word);305KUNIT_EXPECT_EQ(test,306regmap_raw_read(priv->dsp->regmap, reg_addr, readback,307sizeof(readback)),3080);309KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));310311/* Drop expected writes and the cache should then be clean */312cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);313cs_dsp_mock_regmap_drop_range(priv, reg_addr,314reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));315KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));316}317318/*319* bin file with a multiple one-word payloads. The payloads are not in address320* order and collectively do not patch a contiguous block of memory.321*/322static void bin_patch_multi_oneword_sparse_unordered(struct kunit *test)323{324struct cs_dsp_test *priv = test->priv;325const struct bin_test_param *param = test->param_value;326unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);327static const u8 word_offsets[] = {32811, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,32954, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,33029, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22331};332u32 payload_data[44];333unsigned int alg_base_words, reg_addr;334struct firmware *fw;335u32 reg_val;336int i;337338static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(payload_data));339340get_random_bytes(&payload_data, sizeof(payload_data));341342alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,343bin_test_mock_algs[param->alg_idx].id,344param->mem_type);345346/* Add one payload per word */347for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {348cs_dsp_mock_bin_add_patch(priv->local->bin_builder,349bin_test_mock_algs[param->alg_idx].id,350bin_test_mock_algs[param->alg_idx].ver,351param->mem_type,352word_offsets[i] * reg_inc_per_word,353&payload_data[i], sizeof(payload_data[i]));354}355356fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);357KUNIT_ASSERT_EQ(test,358cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",359fw, "mock_bin", "misc"),3600);361362/* Content of registers should match payload_data */363for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {364reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +365((alg_base_words + word_offsets[i]) * reg_inc_per_word);366reg_val = 0;367KUNIT_EXPECT_EQ(test,368regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,369sizeof(reg_val)),3700);371KUNIT_EXPECT_MEMEQ(test, ®_val, &payload_data[i], sizeof(reg_val));372373/* Drop expected writes from the cache */374cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);375}376377/* Drop expected writes and the cache should then be clean */378cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);379KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));380}381382/*383* bin file that patches a single DSP word in each of the memory regions384* of one algorithm.385*/386static void bin_patch_one_word_multiple_mems(struct kunit *test)387{388struct cs_dsp_test *priv = test->priv;389const struct bin_test_param *param = test->param_value;390unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);391unsigned int alg_xm_base_words, alg_ym_base_words, alg_zm_base_words;392unsigned int reg_addr;393u32 payload_data[3];394struct firmware *fw;395u32 reg_val;396397get_random_bytes(&payload_data, sizeof(payload_data));398399alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,400bin_test_mock_algs[param->alg_idx].id,401WMFW_ADSP2_XM);402alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,403bin_test_mock_algs[param->alg_idx].id,404WMFW_ADSP2_YM);405406if (cs_dsp_mock_has_zm(priv)) {407alg_zm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,408bin_test_mock_algs[param->alg_idx].id,409WMFW_ADSP2_ZM);410} else {411alg_zm_base_words = 0;412}413414/* Add words to XM, YM and ZM */415cs_dsp_mock_bin_add_patch(priv->local->bin_builder,416bin_test_mock_algs[param->alg_idx].id,417bin_test_mock_algs[param->alg_idx].ver,418WMFW_ADSP2_XM,419param->offset_words * reg_inc_per_word,420&payload_data[0], sizeof(payload_data[0]));421422cs_dsp_mock_bin_add_patch(priv->local->bin_builder,423bin_test_mock_algs[param->alg_idx].id,424bin_test_mock_algs[param->alg_idx].ver,425WMFW_ADSP2_YM,426param->offset_words * reg_inc_per_word,427&payload_data[1], sizeof(payload_data[1]));428429if (cs_dsp_mock_has_zm(priv)) {430cs_dsp_mock_bin_add_patch(priv->local->bin_builder,431bin_test_mock_algs[param->alg_idx].id,432bin_test_mock_algs[param->alg_idx].ver,433WMFW_ADSP2_ZM,434param->offset_words * reg_inc_per_word,435&payload_data[2], sizeof(payload_data[2]));436}437438fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);439KUNIT_ASSERT_EQ(test,440cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",441fw, "mock_bin", "misc"),4420);443444/* Content of registers should match payload_data */445reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM) +446((alg_xm_base_words + param->offset_words) * reg_inc_per_word);447reg_val = 0;448KUNIT_EXPECT_EQ(test,449regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),4500);451KUNIT_EXPECT_EQ(test, reg_val, payload_data[0]);452453cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);454455reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM) +456((alg_ym_base_words + param->offset_words) * reg_inc_per_word);457reg_val = 0;458KUNIT_EXPECT_EQ(test,459regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),4600);461KUNIT_EXPECT_EQ(test, reg_val, payload_data[1]);462463cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);464465if (cs_dsp_mock_has_zm(priv)) {466reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM) +467((alg_zm_base_words + param->offset_words) * reg_inc_per_word);468reg_val = 0;469KUNIT_EXPECT_EQ(test,470regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,471sizeof(reg_val)),4720);473KUNIT_EXPECT_EQ(test, reg_val, payload_data[2]);474475/* Drop expected writes from the cache */476cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);477}478479/* Drop expected writes and the cache should then be clean */480cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);481KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));482}483484/*485* bin file that patches a single DSP word in multiple algorithms.486*/487static void bin_patch_one_word_multiple_algs(struct kunit *test)488{489struct cs_dsp_test *priv = test->priv;490const struct bin_test_param *param = test->param_value;491u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];492unsigned int alg_base_words;493unsigned int reg_inc_per_word, reg_addr;494struct firmware *fw;495u32 reg_val;496int i;497498get_random_bytes(&payload_data, sizeof(payload_data));499500/* Add one payload per algorithm */501for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {502reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);503504cs_dsp_mock_bin_add_patch(priv->local->bin_builder,505bin_test_mock_algs[i].id,506bin_test_mock_algs[i].ver,507param->mem_type,508param->offset_words * reg_inc_per_word,509&payload_data[i], sizeof(payload_data[i]));510}511512fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);513KUNIT_ASSERT_EQ(test,514cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",515fw, "mock_bin", "misc"),5160);517518/* Content of registers should match payload_data */519for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {520alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,521bin_test_mock_algs[i].id,522param->mem_type);523reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);524reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +525((alg_base_words + param->offset_words) * reg_inc_per_word);526reg_val = 0;527KUNIT_EXPECT_EQ(test,528regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,529sizeof(reg_val)),5300);531KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);532533/* Drop expected writes from the cache */534cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);535}536537/* Drop expected writes and the cache should then be clean */538cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);539KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));540}541542/*543* bin file that patches a single DSP word in multiple algorithms.544* The algorithms are not patched in the same order they appear in the XM header.545*/546static void bin_patch_one_word_multiple_algs_unordered(struct kunit *test)547{548struct cs_dsp_test *priv = test->priv;549const struct bin_test_param *param = test->param_value;550static const u8 alg_order[] = { 3, 0, 2, 1 };551u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];552unsigned int alg_base_words;553unsigned int reg_inc_per_word, reg_addr;554struct firmware *fw;555u32 reg_val;556int i, alg_idx;557558static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));559560get_random_bytes(&payload_data, sizeof(payload_data));561562/* Add one payload per algorithm */563for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {564alg_idx = alg_order[i];565reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);566567cs_dsp_mock_bin_add_patch(priv->local->bin_builder,568bin_test_mock_algs[alg_idx].id,569bin_test_mock_algs[alg_idx].ver,570param->mem_type,571param->offset_words * reg_inc_per_word,572&payload_data[i], sizeof(payload_data[i]));573}574575fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);576KUNIT_ASSERT_EQ(test,577cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",578fw, "mock_bin", "misc"),5790);580581/* Content of registers should match payload_data */582for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {583alg_idx = alg_order[i];584alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,585bin_test_mock_algs[alg_idx].id,586param->mem_type);587reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);588reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +589((alg_base_words + param->offset_words) * reg_inc_per_word);590reg_val = 0;591KUNIT_EXPECT_EQ(test,592regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val,593sizeof(reg_val)),5940);595KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);596597/* Drop expected writes from the cache */598cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);599}600601/* Drop expected writes and the cache should then be clean */602cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);603KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));604}605606/* bin file that patches a single packed block of DSP words */607static void bin_patch_1_packed(struct kunit *test)608{609struct cs_dsp_test *priv = test->priv;610const struct bin_test_param *param = test->param_value;611u32 packed_payload[3], readback[3];612unsigned int alg_base_words, patch_pos_words;613unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;614unsigned int reg_addr;615struct firmware *fw;616617static_assert(sizeof(readback) == sizeof(packed_payload));618619get_random_bytes(packed_payload, sizeof(packed_payload));620621alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,622bin_test_mock_algs[param->alg_idx].id,623param->mem_type);624alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);625626/* Round patch start word up to a packed boundary */627patch_pos_words = round_up(alg_base_words + param->offset_words, 4);628patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);629630cs_dsp_mock_bin_add_patch(priv->local->bin_builder,631bin_test_mock_algs[param->alg_idx].id,632bin_test_mock_algs[param->alg_idx].ver,633param->mem_type,634(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,635packed_payload, sizeof(packed_payload));636637fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);638KUNIT_ASSERT_EQ(test,639cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",640fw, "mock_bin", "misc"),6410);642643/* Content of registers should match payload_data */644reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +645(patch_pos_in_packed_regs * 4);646memset(readback, 0, sizeof(readback));647KUNIT_EXPECT_EQ(test,648regmap_raw_read(priv->dsp->regmap, reg_addr, readback,649sizeof(readback)),6500);651KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));652653/* Drop expected writes and the cache should then be clean */654cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);655cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));656KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));657}658659/*660* Patch data that is one word longer than a packed block using one661* packed block followed by one unpacked word.662*/663static void bin_patch_1_packed_1_single_trailing(struct kunit *test)664{665struct cs_dsp_test *priv = test->priv;666const struct bin_test_param *param = test->param_value;667unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);668u32 packed_payload[3], unpacked_payload[1], readback[3];669unsigned int alg_base_words, patch_pos_words;670unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;671unsigned int reg_addr;672struct firmware *fw;673674static_assert(sizeof(readback) == sizeof(packed_payload));675static_assert(sizeof(readback) >= sizeof(unpacked_payload));676677get_random_bytes(packed_payload, sizeof(packed_payload));678get_random_bytes(unpacked_payload, sizeof(unpacked_payload));679680alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,681bin_test_mock_algs[param->alg_idx].id,682param->mem_type);683alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);684685/* Round patch start word up to a packed boundary */686patch_pos_words = round_up(alg_base_words + param->offset_words, 4);687patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);688689/* Patch packed block */690cs_dsp_mock_bin_add_patch(priv->local->bin_builder,691bin_test_mock_algs[param->alg_idx].id,692bin_test_mock_algs[param->alg_idx].ver,693param->mem_type,694(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,695&packed_payload, sizeof(packed_payload));696697/* ... and the unpacked word following that */698cs_dsp_mock_bin_add_patch(priv->local->bin_builder,699bin_test_mock_algs[param->alg_idx].id,700bin_test_mock_algs[param->alg_idx].ver,701unpacked_mem_type,702((patch_pos_words + 4) - alg_base_words) * 4,703unpacked_payload, sizeof(unpacked_payload));704705fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);706KUNIT_ASSERT_EQ(test,707cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",708fw, "mock_bin", "misc"),7090);710711/* Content of packed registers should match packed_payload */712reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +713(patch_pos_in_packed_regs * 4);714memset(readback, 0, sizeof(readback));715KUNIT_EXPECT_EQ(test,716regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),7170);718KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));719720cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));721722/* Content of unpacked registers should match unpacked_payload */723reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +724(patch_pos_words + 4) * 4;725memset(readback, 0, sizeof(readback));726KUNIT_EXPECT_EQ(test,727regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,728sizeof(unpacked_payload)),7290);730KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));731732cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));733734/* Drop expected writes and the cache should then be clean */735cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);736KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));737}738739/*740* Patch data that is two words longer than a packed block using one741* packed block followed by two blocks of one unpacked word.742*/743static void bin_patch_1_packed_2_single_trailing(struct kunit *test)744{745struct cs_dsp_test *priv = test->priv;746const struct bin_test_param *param = test->param_value;747unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);748u32 packed_payload[3], unpacked_payloads[2], readback[3];749unsigned int alg_base_words, patch_pos_words;750unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;751unsigned int reg_addr;752struct firmware *fw;753754static_assert(sizeof(readback) == sizeof(packed_payload));755static_assert(sizeof(readback) >= sizeof(unpacked_payloads));756757get_random_bytes(packed_payload, sizeof(packed_payload));758get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));759760alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,761bin_test_mock_algs[param->alg_idx].id,762param->mem_type);763alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);764765/* Round patch start word up to a packed boundary */766patch_pos_words = round_up(alg_base_words + param->offset_words, 4);767patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);768769/* Patch packed block */770cs_dsp_mock_bin_add_patch(priv->local->bin_builder,771bin_test_mock_algs[param->alg_idx].id,772bin_test_mock_algs[param->alg_idx].ver,773param->mem_type,774(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,775&packed_payload, sizeof(packed_payload));776777/* ... and the unpacked words following that */778cs_dsp_mock_bin_add_patch(priv->local->bin_builder,779bin_test_mock_algs[param->alg_idx].id,780bin_test_mock_algs[param->alg_idx].ver,781unpacked_mem_type,782((patch_pos_words + 4) - alg_base_words) * 4,783&unpacked_payloads[0], sizeof(unpacked_payloads[0]));784785cs_dsp_mock_bin_add_patch(priv->local->bin_builder,786bin_test_mock_algs[param->alg_idx].id,787bin_test_mock_algs[param->alg_idx].ver,788unpacked_mem_type,789((patch_pos_words + 5) - alg_base_words) * 4,790&unpacked_payloads[1], sizeof(unpacked_payloads[1]));791792fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);793KUNIT_ASSERT_EQ(test,794cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",795fw, "mock_bin", "misc"),7960);797798/* Content of packed registers should match packed_payload */799reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +800(patch_pos_in_packed_regs * 4);801memset(readback, 0, sizeof(readback));802KUNIT_EXPECT_EQ(test,803regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),8040);805KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));806807/* Drop expected writes from the cache */808cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));809810/* Content of unpacked registers should match unpacked_payloads */811reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +812(patch_pos_words + 4) * 4;813memset(readback, 0, sizeof(readback));814KUNIT_EXPECT_EQ(test,815regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,816sizeof(unpacked_payloads)),8170);818KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));819820/* Drop expected writes from the cache */821cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));822823/* Drop expected writes and the cache should then be clean */824cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);825KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));826}827828/*829* Patch data that is three words longer than a packed block using one830* packed block followed by three blocks of one unpacked word.831*/832static void bin_patch_1_packed_3_single_trailing(struct kunit *test)833{834struct cs_dsp_test *priv = test->priv;835const struct bin_test_param *param = test->param_value;836unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);837u32 packed_payload[3], unpacked_payloads[3], readback[3];838unsigned int alg_base_words, patch_pos_words;839unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;840unsigned int reg_addr;841struct firmware *fw;842843static_assert(sizeof(readback) == sizeof(packed_payload));844static_assert(sizeof(readback) >= sizeof(unpacked_payloads));845846get_random_bytes(packed_payload, sizeof(packed_payload));847get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));848849alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,850bin_test_mock_algs[param->alg_idx].id,851param->mem_type);852alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);853854/* Round patch start word up to a packed boundary */855patch_pos_words = round_up(alg_base_words + param->offset_words, 4);856patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);857858/* Patch packed block */859cs_dsp_mock_bin_add_patch(priv->local->bin_builder,860bin_test_mock_algs[param->alg_idx].id,861bin_test_mock_algs[param->alg_idx].ver,862param->mem_type,863(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,864&packed_payload, sizeof(packed_payload));865866/* ... and the unpacked words following that */867cs_dsp_mock_bin_add_patch(priv->local->bin_builder,868bin_test_mock_algs[param->alg_idx].id,869bin_test_mock_algs[param->alg_idx].ver,870unpacked_mem_type,871((patch_pos_words + 4) - alg_base_words) * 4,872&unpacked_payloads[0], sizeof(unpacked_payloads[0]));873874cs_dsp_mock_bin_add_patch(priv->local->bin_builder,875bin_test_mock_algs[param->alg_idx].id,876bin_test_mock_algs[param->alg_idx].ver,877unpacked_mem_type,878((patch_pos_words + 5) - alg_base_words) * 4,879&unpacked_payloads[1], sizeof(unpacked_payloads[1]));880881cs_dsp_mock_bin_add_patch(priv->local->bin_builder,882bin_test_mock_algs[param->alg_idx].id,883bin_test_mock_algs[param->alg_idx].ver,884unpacked_mem_type,885((patch_pos_words + 6) - alg_base_words) * 4,886&unpacked_payloads[2], sizeof(unpacked_payloads[2]));887888fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);889KUNIT_ASSERT_EQ(test,890cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",891fw, "mock_bin", "misc"),8920);893894/* Content of packed registers should match packed_payload */895reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +896(patch_pos_in_packed_regs * 4);897memset(readback, 0, sizeof(readback));898KUNIT_EXPECT_EQ(test,899regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),9000);901KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));902903/* Drop expected writes from the cache */904cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));905906/* Content of unpacked registers should match unpacked_payloads */907reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +908(patch_pos_words + 4) * 4;909memset(readback, 0, sizeof(readback));910KUNIT_EXPECT_EQ(test,911regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,912sizeof(unpacked_payloads)),9130);914KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));915916/* Drop expected writes from the cache */917cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));918919/* Drop expected writes and the cache should then be clean */920cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);921KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));922}923924/*925* Patch data that is two words longer than a packed block using one926* packed block followed by a block of two unpacked words.927*/928static void bin_patch_1_packed_2_trailing(struct kunit *test)929{930struct cs_dsp_test *priv = test->priv;931const struct bin_test_param *param = test->param_value;932unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);933u32 packed_payload[3], unpacked_payload[2], readback[3];934unsigned int alg_base_words, patch_pos_words;935unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;936unsigned int reg_addr;937struct firmware *fw;938939static_assert(sizeof(readback) == sizeof(packed_payload));940static_assert(sizeof(readback) >= sizeof(unpacked_payload));941942get_random_bytes(packed_payload, sizeof(packed_payload));943get_random_bytes(unpacked_payload, sizeof(unpacked_payload));944945alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,946bin_test_mock_algs[param->alg_idx].id,947param->mem_type);948alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);949950/* Round patch start word up to a packed boundary */951patch_pos_words = round_up(alg_base_words + param->offset_words, 4);952patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);953954/* Patch packed block */955cs_dsp_mock_bin_add_patch(priv->local->bin_builder,956bin_test_mock_algs[param->alg_idx].id,957bin_test_mock_algs[param->alg_idx].ver,958param->mem_type,959(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,960&packed_payload, sizeof(packed_payload));961962/* ... and the unpacked words following that */963cs_dsp_mock_bin_add_patch(priv->local->bin_builder,964bin_test_mock_algs[param->alg_idx].id,965bin_test_mock_algs[param->alg_idx].ver,966unpacked_mem_type,967((patch_pos_words + 4) - alg_base_words) * 4,968unpacked_payload, sizeof(unpacked_payload));969970fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);971KUNIT_ASSERT_EQ(test,972cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",973fw, "mock_bin", "misc"),9740);975976/* Content of packed registers should match packed_payload */977reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +978(patch_pos_in_packed_regs * 4);979memset(readback, 0, sizeof(readback));980KUNIT_EXPECT_EQ(test,981regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),9820);983KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));984985/* Drop expected writes from the cache */986cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));987988/* Content of unpacked registers should match unpacked_payload */989reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +990(patch_pos_words + 4) * 4;991memset(readback, 0, sizeof(readback));992KUNIT_EXPECT_EQ(test,993regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,994sizeof(unpacked_payload)),9950);996KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));997998/* Drop expected writes from the cache */999cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));10001001/* Drop expected writes and the cache should then be clean */1002cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1003KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1004}10051006/*1007* Patch data that is three words longer than a packed block using one1008* packed block followed by a block of three unpacked words.1009*/1010static void bin_patch_1_packed_3_trailing(struct kunit *test)1011{1012struct cs_dsp_test *priv = test->priv;1013const struct bin_test_param *param = test->param_value;1014unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1015u32 packed_payload[3], unpacked_payload[3], readback[3];1016unsigned int alg_base_words, patch_pos_words;1017unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1018unsigned int reg_addr;1019struct firmware *fw;10201021static_assert(sizeof(readback) == sizeof(packed_payload));1022static_assert(sizeof(readback) >= sizeof(unpacked_payload));10231024get_random_bytes(packed_payload, sizeof(packed_payload));1025get_random_bytes(unpacked_payload, sizeof(unpacked_payload));10261027alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1028bin_test_mock_algs[param->alg_idx].id,1029param->mem_type);1030alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);10311032/* Round patch start word up to a packed boundary */1033patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1034patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);10351036/* Patch packed block */1037cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1038bin_test_mock_algs[param->alg_idx].id,1039bin_test_mock_algs[param->alg_idx].ver,1040param->mem_type,1041(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1042&packed_payload, sizeof(packed_payload));10431044/* ... and the unpacked words following that */1045cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1046bin_test_mock_algs[param->alg_idx].id,1047bin_test_mock_algs[param->alg_idx].ver,1048unpacked_mem_type,1049((patch_pos_words + 4) - alg_base_words) * 4,1050unpacked_payload, sizeof(unpacked_payload));10511052fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1053KUNIT_ASSERT_EQ(test,1054cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1055fw, "mock_bin", "misc"),10560);10571058/* Content of packed registers should match packed_payload */1059reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1060(patch_pos_in_packed_regs * 4);1061memset(readback, 0, sizeof(readback));1062KUNIT_EXPECT_EQ(test,1063regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),10640);1065KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));10661067/* Drop expected writes from the cache */1068cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));10691070/* Content of unpacked registers should match unpacked_payload */1071reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1072(patch_pos_words + 4) * 4;1073memset(readback, 0, sizeof(readback));1074KUNIT_EXPECT_EQ(test,1075regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1076sizeof(unpacked_payload)),10770);1078KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));10791080/* Drop expected writes from the cache */1081cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));10821083/* Drop expected writes and the cache should then be clean */1084cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1085KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1086}10871088/*1089* Patch data that starts one word before a packed boundary using one1090* unpacked word followed by one packed block.1091*/1092static void bin_patch_1_single_leading_1_packed(struct kunit *test)1093{1094struct cs_dsp_test *priv = test->priv;1095const struct bin_test_param *param = test->param_value;1096unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1097u32 packed_payload[3], unpacked_payload[1], readback[3];1098unsigned int alg_base_words, packed_patch_pos_words;1099unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1100unsigned int reg_addr;1101struct firmware *fw;11021103static_assert(sizeof(readback) == sizeof(packed_payload));1104static_assert(sizeof(readback) >= sizeof(unpacked_payload));11051106get_random_bytes(packed_payload, sizeof(packed_payload));1107get_random_bytes(unpacked_payload, sizeof(unpacked_payload));1108memset(readback, 0, sizeof(readback));11091110alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1111bin_test_mock_algs[param->alg_idx].id,1112param->mem_type);1113alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);11141115/* Round packed start word up to a packed boundary and move to the next boundary */1116packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;11171118/* Patch the leading unpacked word */1119cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1120bin_test_mock_algs[param->alg_idx].id,1121bin_test_mock_algs[param->alg_idx].ver,1122unpacked_mem_type,1123((packed_patch_pos_words - 1) - alg_base_words) * 4,1124unpacked_payload, sizeof(unpacked_payload));1125/* ... then the packed block */1126patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1127cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1128bin_test_mock_algs[param->alg_idx].id,1129bin_test_mock_algs[param->alg_idx].ver,1130param->mem_type,1131(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1132&packed_payload, sizeof(packed_payload));11331134fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1135KUNIT_ASSERT_EQ(test,1136cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1137fw, "mock_bin", "misc"),11380);11391140/* Content of packed registers should match packed_payload */1141reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1142(patch_pos_in_packed_regs * 4);1143KUNIT_EXPECT_EQ(test,1144regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),11450);1146KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));11471148/* Drop expected writes from the cache */1149cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));11501151/* Content of unpacked registers should match unpacked_payload */1152reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1153(packed_patch_pos_words - 1) * 4;1154KUNIT_EXPECT_EQ(test,1155regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1156sizeof(unpacked_payload)),11570);1158KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));11591160/* Drop expected writes from the cache */1161cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));11621163/* Drop expected writes and the cache should then be clean */1164cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1165KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1166}11671168/*1169* Patch data that starts two words before a packed boundary using two1170* unpacked words followed by one packed block.1171*/1172static void bin_patch_2_single_leading_1_packed(struct kunit *test)1173{1174struct cs_dsp_test *priv = test->priv;1175const struct bin_test_param *param = test->param_value;1176unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1177u32 packed_payload[3], unpacked_payload[2], readback[3];1178unsigned int alg_base_words, packed_patch_pos_words;1179unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1180unsigned int reg_addr;1181struct firmware *fw;11821183static_assert(sizeof(readback) == sizeof(packed_payload));1184static_assert(sizeof(readback) >= sizeof(unpacked_payload));11851186get_random_bytes(packed_payload, sizeof(packed_payload));1187get_random_bytes(unpacked_payload, sizeof(unpacked_payload));11881189alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1190bin_test_mock_algs[param->alg_idx].id,1191param->mem_type);1192alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);11931194/* Round packed start word up to a packed boundary and move to the next boundary */1195packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;11961197/* Patch the leading unpacked words */1198cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1199bin_test_mock_algs[param->alg_idx].id,1200bin_test_mock_algs[param->alg_idx].ver,1201unpacked_mem_type,1202((packed_patch_pos_words - 2) - alg_base_words) * 4,1203&unpacked_payload[0], sizeof(unpacked_payload[0]));1204cs_dsp_mock_bin_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 - 1) - alg_base_words) * 4,1209&unpacked_payload[1], sizeof(unpacked_payload[1]));1210/* ... then the packed block */1211patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1212cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1213bin_test_mock_algs[param->alg_idx].id,1214bin_test_mock_algs[param->alg_idx].ver,1215param->mem_type,1216(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1217&packed_payload, sizeof(packed_payload));12181219fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1220KUNIT_ASSERT_EQ(test,1221cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1222fw, "mock_bin", "misc"),12230);12241225/* Content of packed registers should match packed_payload */1226reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1227(patch_pos_in_packed_regs * 4);1228memset(readback, 0, sizeof(readback));1229KUNIT_EXPECT_EQ(test,1230regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),12310);1232KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));12331234/* Drop expected writes from the cache */1235cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));12361237/* Content of unpacked registers should match unpacked_payload */1238reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1239(packed_patch_pos_words - 2) * 4;1240memset(readback, 0, sizeof(readback));1241KUNIT_EXPECT_EQ(test,1242regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1243sizeof(unpacked_payload)),12440);1245KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));12461247/* Drop expected writes from the cache */1248cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));12491250/* Drop expected writes and the cache should then be clean */1251cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1252KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1253}12541255/*1256* Patch data that starts two words before a packed boundary using one1257* block of two unpacked words followed by one packed block.1258*/1259static void bin_patch_2_leading_1_packed(struct kunit *test)1260{1261struct cs_dsp_test *priv = test->priv;1262const struct bin_test_param *param = test->param_value;1263unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1264u32 packed_payload[3], unpacked_payload[2], readback[3];1265unsigned int alg_base_words, packed_patch_pos_words;1266unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1267unsigned int reg_addr;1268struct firmware *fw;12691270static_assert(sizeof(readback) == sizeof(packed_payload));1271static_assert(sizeof(readback) >= sizeof(unpacked_payload));12721273get_random_bytes(packed_payload, sizeof(packed_payload));1274get_random_bytes(unpacked_payload, sizeof(unpacked_payload));12751276alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1277bin_test_mock_algs[param->alg_idx].id,1278param->mem_type);1279alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);12801281/* Round packed start word up to a packed boundary and move to the next boundary */1282packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;12831284/* Patch the leading unpacked words */1285cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1286bin_test_mock_algs[param->alg_idx].id,1287bin_test_mock_algs[param->alg_idx].ver,1288unpacked_mem_type,1289((packed_patch_pos_words - 2) - alg_base_words) * 4,1290unpacked_payload, sizeof(unpacked_payload));1291/* ... then the packed block */1292patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1293cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1294bin_test_mock_algs[param->alg_idx].id,1295bin_test_mock_algs[param->alg_idx].ver,1296param->mem_type,1297(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1298&packed_payload, sizeof(packed_payload));12991300fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1301KUNIT_ASSERT_EQ(test,1302cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1303fw, "mock_bin", "misc"),13040);13051306/* Content of packed registers should match packed_payload */1307reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1308(patch_pos_in_packed_regs * 4);1309memset(readback, 0, sizeof(readback));1310KUNIT_EXPECT_EQ(test,1311regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),13120);1313KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));13141315/* Drop expected writes from the cache */1316cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));13171318/* Content of unpacked registers should match unpacked_payload */1319reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1320(packed_patch_pos_words - 2) * 4;1321memset(readback, 0, sizeof(readback));1322KUNIT_EXPECT_EQ(test,1323regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1324sizeof(unpacked_payload)),13250);1326KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));13271328/* Drop expected writes from the cache */1329cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));13301331/* Drop expected writes and the cache should then be clean */1332cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1333KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1334}13351336/*1337* Patch data that starts three words before a packed boundary using three1338* unpacked words followed by one packed block.1339*/1340static void bin_patch_3_single_leading_1_packed(struct kunit *test)1341{1342struct cs_dsp_test *priv = test->priv;1343const struct bin_test_param *param = test->param_value;1344unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1345u32 packed_payload[3], unpacked_payload[3], readback[3];1346unsigned int alg_base_words, packed_patch_pos_words;1347unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1348unsigned int reg_addr;1349struct firmware *fw;13501351static_assert(sizeof(readback) == sizeof(packed_payload));1352static_assert(sizeof(readback) >= sizeof(unpacked_payload));13531354get_random_bytes(packed_payload, sizeof(packed_payload));1355get_random_bytes(unpacked_payload, sizeof(unpacked_payload));13561357alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1358bin_test_mock_algs[param->alg_idx].id,1359param->mem_type);1360alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);13611362/* Round packed start word up to a packed boundary and move to the next boundary */1363packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;13641365/* Patch the leading unpacked words */1366cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1367bin_test_mock_algs[param->alg_idx].id,1368bin_test_mock_algs[param->alg_idx].ver,1369unpacked_mem_type,1370((packed_patch_pos_words - 3) - alg_base_words) * 4,1371&unpacked_payload[0], sizeof(unpacked_payload[0]));1372cs_dsp_mock_bin_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 - 2) - alg_base_words) * 4,1377&unpacked_payload[1], sizeof(unpacked_payload[1]));1378cs_dsp_mock_bin_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 - 1) - alg_base_words) * 4,1383&unpacked_payload[2], sizeof(unpacked_payload[2]));1384/* ... then the packed block */1385patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1386cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1387bin_test_mock_algs[param->alg_idx].id,1388bin_test_mock_algs[param->alg_idx].ver,1389param->mem_type,1390(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1391&packed_payload, sizeof(packed_payload));13921393fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1394KUNIT_ASSERT_EQ(test,1395cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1396fw, "mock_bin", "misc"),13970);13981399/* Content of packed registers should match packed_payload */1400reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1401(patch_pos_in_packed_regs * 4);1402memset(readback, 0, sizeof(readback));1403KUNIT_EXPECT_EQ(test,1404regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),14050);1406KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));14071408/* Drop expected writes from the cache */1409cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));14101411/* Content of unpacked registers should match unpacked_payload */1412reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1413(packed_patch_pos_words - 3) * 4;1414memset(readback, 0, sizeof(readback));1415KUNIT_EXPECT_EQ(test,1416regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1417sizeof(unpacked_payload)),14180);1419KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));14201421/* Drop expected writes from the cache */1422cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));14231424/* Drop expected writes and the cache should then be clean */1425cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1426KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1427}14281429/*1430* Patch data that starts three words before a packed boundary using one1431* block of three unpacked words followed by one packed block.1432*/1433static void bin_patch_3_leading_1_packed(struct kunit *test)1434{1435struct cs_dsp_test *priv = test->priv;1436const struct bin_test_param *param = test->param_value;1437unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1438u32 packed_payload[3], unpacked_payload[3], readback[3];1439unsigned int alg_base_words, packed_patch_pos_words;1440unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1441unsigned int reg_addr;1442struct firmware *fw;14431444static_assert(sizeof(readback) == sizeof(packed_payload));1445static_assert(sizeof(readback) >= sizeof(unpacked_payload));14461447get_random_bytes(packed_payload, sizeof(packed_payload));1448get_random_bytes(unpacked_payload, sizeof(unpacked_payload));14491450alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1451bin_test_mock_algs[param->alg_idx].id,1452param->mem_type);1453alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);14541455/* Round packed start word up to a packed boundary and move to the next boundary */1456packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;14571458/* Patch the leading unpacked words */1459cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1460bin_test_mock_algs[param->alg_idx].id,1461bin_test_mock_algs[param->alg_idx].ver,1462unpacked_mem_type,1463((packed_patch_pos_words - 3) - alg_base_words) * 4,1464unpacked_payload, sizeof(unpacked_payload));1465/* ... then the packed block */1466patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);1467cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1468bin_test_mock_algs[param->alg_idx].id,1469bin_test_mock_algs[param->alg_idx].ver,1470param->mem_type,1471(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1472&packed_payload, sizeof(packed_payload));14731474fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1475KUNIT_ASSERT_EQ(test,1476cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1477fw, "mock_bin", "misc"),14780);14791480/* Content of packed registers should match packed_payload */1481reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1482(patch_pos_in_packed_regs * 4);1483memset(readback, 0, sizeof(readback));1484KUNIT_EXPECT_EQ(test,1485regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),14860);1487KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));14881489/* Drop expected writes from the cache */1490cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));14911492/* Content of unpacked registers should match unpacked_payload */1493reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +1494(packed_patch_pos_words - 3) * 4;1495memset(readback, 0, sizeof(readback));1496KUNIT_EXPECT_EQ(test,1497regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,1498sizeof(unpacked_payload)),14990);1500KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));15011502/* Drop expected writes from the cache */1503cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));15041505/* Drop expected writes and the cache should then be clean */1506cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1507KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1508}15091510/* bin file with a multiple payloads that each patch one packed block. */1511static void bin_patch_multi_onepacked(struct kunit *test)1512{1513struct cs_dsp_test *priv = test->priv;1514const struct bin_test_param *param = test->param_value;1515u32 packed_payloads[8][3], readback[8][3];1516unsigned int alg_base_words, patch_pos_words;1517unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1518unsigned int payload_offset;1519unsigned int reg_addr;1520struct firmware *fw;1521int i;15221523static_assert(sizeof(readback) == sizeof(packed_payloads));15241525get_random_bytes(packed_payloads, sizeof(packed_payloads));15261527alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1528bin_test_mock_algs[param->alg_idx].id,1529param->mem_type);1530alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);15311532/* Round patch start word up to a packed boundary */1533patch_pos_words = round_up(alg_base_words + param->offset_words, 4);15341535/* Add one payload per packed block */1536for (i = 0; i < ARRAY_SIZE(packed_payloads); ++i) {1537patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words + (i * 4));1538payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1539cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1540bin_test_mock_algs[param->alg_idx].id,1541bin_test_mock_algs[param->alg_idx].ver,1542param->mem_type,1543payload_offset,1544&packed_payloads[i], sizeof(packed_payloads[i]));1545}15461547fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1548KUNIT_ASSERT_EQ(test,1549cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1550fw, "mock_bin", "misc"),15510);15521553/* Content of packed registers should match packed_payloads */1554patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1555reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1556(patch_pos_in_packed_regs * 4);1557memset(readback, 0, sizeof(readback));1558KUNIT_EXPECT_EQ(test,1559regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),15600);1561KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));15621563/* Drop expected writes and the cache should then be clean */1564cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1565cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));1566KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1567}15681569/*1570* bin file with a multiple payloads that each patch one packed block.1571* The payloads are not in address order.1572*/1573static void bin_patch_multi_onepacked_unordered(struct kunit *test)1574{1575struct cs_dsp_test *priv = test->priv;1576const struct bin_test_param *param = test->param_value;1577static const u8 payload_order[] = { 4, 3, 6, 1, 0, 7, 5, 2 };1578u32 packed_payloads[8][3], readback[8][3];1579unsigned int alg_base_words, patch_pos_words;1580unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1581unsigned int payload_offset;1582unsigned int reg_addr;1583struct firmware *fw;1584int i;15851586static_assert(ARRAY_SIZE(payload_order) == ARRAY_SIZE(packed_payloads));1587static_assert(sizeof(readback) == sizeof(packed_payloads));15881589get_random_bytes(packed_payloads, sizeof(packed_payloads));15901591alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1592bin_test_mock_algs[param->alg_idx].id,1593param->mem_type);1594alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);15951596/* Round patch start word up to a packed boundary */1597patch_pos_words = round_up(alg_base_words + param->offset_words, 4);15981599/* Add one payload per packed block */1600for (i = 0; i < ARRAY_SIZE(payload_order); ++i) {1601patch_pos_in_packed_regs =1602_num_words_to_num_packed_regs(patch_pos_words + (payload_order[i] * 4));1603payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1604cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1605bin_test_mock_algs[param->alg_idx].id,1606bin_test_mock_algs[param->alg_idx].ver,1607param->mem_type,1608payload_offset,1609&packed_payloads[payload_order[i]],1610sizeof(packed_payloads[0]));1611}16121613fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1614KUNIT_ASSERT_EQ(test,1615cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1616fw, "mock_bin", "misc"),16170);16181619/* Content in registers should match the order of data in packed_payloads */1620patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1621reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1622(patch_pos_in_packed_regs * 4);1623memset(readback, 0, sizeof(readback));1624KUNIT_EXPECT_EQ(test,1625regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),16260);1627KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));16281629/* Drop expected writes and the cache should then be clean */1630cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1631cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));1632KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1633}16341635/*1636* bin file with a multiple payloads that each patch one packed block.1637* The payloads are not in address order. The patched memory is not contiguous.1638*/1639static void bin_patch_multi_onepacked_sparse_unordered(struct kunit *test)1640{1641struct cs_dsp_test *priv = test->priv;1642const struct bin_test_param *param = test->param_value;1643static const u8 word_offsets[] = { 60, 24, 76, 4, 40, 52, 48, 36, 12 };1644u32 packed_payloads[9][3], readback[3];1645unsigned int alg_base_words, alg_base_in_packed_regs;1646unsigned int patch_pos_words, patch_pos_in_packed_regs, payload_offset;1647unsigned int reg_addr;1648struct firmware *fw;1649int i;16501651static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(packed_payloads));1652static_assert(sizeof(readback) == sizeof(packed_payloads[0]));16531654get_random_bytes(packed_payloads, sizeof(packed_payloads));16551656alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1657bin_test_mock_algs[param->alg_idx].id,1658param->mem_type);1659alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);16601661/* Add one payload per packed block */1662for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {1663/* Round patch start word up to a packed boundary */1664patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);1665patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1666payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1667cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1668bin_test_mock_algs[param->alg_idx].id,1669bin_test_mock_algs[param->alg_idx].ver,1670param->mem_type,1671payload_offset,1672&packed_payloads[i],1673sizeof(packed_payloads[0]));1674}16751676fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1677KUNIT_ASSERT_EQ(test,1678cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1679fw, "mock_bin", "misc"),16800);16811682/* Content of packed registers should match packed_payloads */1683for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {1684patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);1685patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);1686reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1687(patch_pos_in_packed_regs * 4);1688memset(readback, 0, sizeof(readback));1689KUNIT_EXPECT_EQ(test,1690regmap_raw_read(priv->dsp->regmap, reg_addr, readback,1691sizeof(readback)),16920);1693KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads[i], sizeof(packed_payloads[i]));16941695/* Drop expected writes from the cache */1696cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads[i]));1697}16981699/* Drop expected writes and the cache should then be clean */1700cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1701KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1702}17031704/*1705* bin file that patches a single packed block in each of the memory regions1706* of one algorithm.1707*/1708static void bin_patch_1_packed_multiple_mems(struct kunit *test)1709{1710struct cs_dsp_test *priv = test->priv;1711const struct bin_test_param *param = test->param_value;1712u32 packed_xm_payload[3], packed_ym_payload[3], readback[3];1713unsigned int alg_xm_base_words, alg_ym_base_words;1714unsigned int xm_patch_pos_words, ym_patch_pos_words;1715unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1716unsigned int reg_addr;1717struct firmware *fw;17181719static_assert(sizeof(readback) == sizeof(packed_xm_payload));1720static_assert(sizeof(readback) == sizeof(packed_ym_payload));17211722get_random_bytes(packed_xm_payload, sizeof(packed_xm_payload));1723get_random_bytes(packed_ym_payload, sizeof(packed_ym_payload));17241725alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1726bin_test_mock_algs[param->alg_idx].id,1727WMFW_HALO_XM_PACKED);1728alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1729bin_test_mock_algs[param->alg_idx].id,1730WMFW_HALO_YM_PACKED);17311732/* Round patch start word up to a packed boundary */1733xm_patch_pos_words = round_up(alg_xm_base_words + param->offset_words, 4);1734ym_patch_pos_words = round_up(alg_ym_base_words + param->offset_words, 4);17351736/* Add XM and YM patches */1737alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_xm_base_words);1738patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);1739cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1740bin_test_mock_algs[param->alg_idx].id,1741bin_test_mock_algs[param->alg_idx].ver,1742WMFW_HALO_XM_PACKED,1743(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1744packed_xm_payload, sizeof(packed_xm_payload));17451746alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_ym_base_words);1747patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);1748cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1749bin_test_mock_algs[param->alg_idx].id,1750bin_test_mock_algs[param->alg_idx].ver,1751WMFW_HALO_YM_PACKED,1752(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,1753packed_ym_payload, sizeof(packed_ym_payload));17541755fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1756KUNIT_ASSERT_EQ(test,1757cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1758fw, "mock_bin", "misc"),17590);17601761/* Content of packed XM registers should match packed_xm_payload */1762patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);1763reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_XM_PACKED) +1764(patch_pos_in_packed_regs * 4);1765memset(readback, 0, sizeof(readback));1766KUNIT_EXPECT_EQ(test,1767regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),17680);1769KUNIT_EXPECT_MEMEQ(test, readback, packed_xm_payload, sizeof(packed_xm_payload));17701771/* Drop expected writes from the cache */1772cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_xm_payload));17731774/* Content of packed YM registers should match packed_ym_payload */1775patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);1776reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_YM_PACKED) +1777(patch_pos_in_packed_regs * 4);1778memset(readback, 0, sizeof(readback));1779KUNIT_EXPECT_EQ(test,1780regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),17810);1782KUNIT_EXPECT_MEMEQ(test, readback, packed_ym_payload, sizeof(packed_ym_payload));17831784/* Drop expected writes from the cache */1785cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_ym_payload));17861787/* Drop expected writes and the cache should then be clean */1788cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1789KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1790}17911792/*1793* bin file that patches a single packed block in multiple algorithms.1794*/1795static void bin_patch_1_packed_multiple_algs(struct kunit *test)1796{1797struct cs_dsp_test *priv = test->priv;1798const struct bin_test_param *param = test->param_value;1799u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];1800u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];1801unsigned int alg_base_words, patch_pos_words;1802unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1803unsigned int reg_addr, payload_offset;1804struct firmware *fw;1805int i;18061807static_assert(sizeof(readback) == sizeof(packed_payload));18081809get_random_bytes(packed_payload, sizeof(packed_payload));18101811/* For each algorithm patch one DSP word to a value from packed_payload */1812for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {1813alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1814bin_test_mock_algs[i].id,1815param->mem_type);1816alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);18171818/* Round patch start word up to a packed boundary */1819patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1820patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);18211822payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1823cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1824bin_test_mock_algs[i].id,1825bin_test_mock_algs[i].ver,1826param->mem_type,1827payload_offset,1828packed_payload[i], sizeof(packed_payload[i]));1829}18301831fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1832KUNIT_ASSERT_EQ(test,1833cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1834fw, "mock_bin", "misc"),18350);18361837memset(readback, 0, sizeof(readback));18381839/*1840* Readback the registers that should have been written. Place1841* the values into the expected location in readback[] so that1842* the content of readback[] should match packed_payload[]1843*/1844for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {1845alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1846bin_test_mock_algs[i].id,1847param->mem_type);1848alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);18491850patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1851patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);18521853reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1854(patch_pos_in_packed_regs * 4);1855KUNIT_EXPECT_EQ(test,1856regmap_raw_read(priv->dsp->regmap, reg_addr,1857readback[i], sizeof(readback[i])),18580);18591860/* Drop expected writes from the cache */1861cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));1862}18631864KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));18651866/* Drop expected writes and the cache should then be clean */1867cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1868KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1869}18701871/*1872* bin file that patches a single packed block in multiple algorithms.1873* The algorithms are not patched in the same order they appear in the XM header.1874*/1875static void bin_patch_1_packed_multiple_algs_unordered(struct kunit *test)1876{1877struct cs_dsp_test *priv = test->priv;1878const struct bin_test_param *param = test->param_value;1879static const u8 alg_order[] = { 3, 0, 2, 1 };1880u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];1881u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];1882unsigned int alg_base_words, patch_pos_words;1883unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1884unsigned int reg_addr, payload_offset;1885struct firmware *fw;1886int i, alg_idx;18871888static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));1889static_assert(sizeof(readback) == sizeof(packed_payload));18901891get_random_bytes(packed_payload, sizeof(packed_payload));18921893/*1894* For each algorithm index in alg_order[] patch one DSP word in1895* that algorithm to a value from packed_payload.1896*/1897for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {1898alg_idx = alg_order[i];1899alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1900bin_test_mock_algs[alg_idx].id,1901param->mem_type);1902alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);19031904/* Round patch start word up to a packed boundary */1905patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1906patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);19071908payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;1909cs_dsp_mock_bin_add_patch(priv->local->bin_builder,1910bin_test_mock_algs[alg_idx].id,1911bin_test_mock_algs[alg_idx].ver,1912param->mem_type,1913payload_offset,1914packed_payload[i], sizeof(packed_payload[i]));1915}19161917fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);1918KUNIT_ASSERT_EQ(test,1919cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",1920fw, "mock_bin", "misc"),19210);19221923memset(readback, 0, sizeof(readback));19241925/*1926* Readback the registers that should have been written. Place1927* the values into the expected location in readback[] so that1928* the content of readback[] should match packed_payload[]1929*/1930for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {1931alg_idx = alg_order[i];1932alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1933bin_test_mock_algs[alg_idx].id,1934param->mem_type);19351936patch_pos_words = round_up(alg_base_words + param->offset_words, 4);1937patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);19381939reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +1940(patch_pos_in_packed_regs * 4);1941KUNIT_EXPECT_EQ(test,1942regmap_raw_read(priv->dsp->regmap, reg_addr,1943readback[i], sizeof(readback[i])),19440);19451946/* Drop expected writes from the cache */1947cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));1948}19491950KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));19511952/* Drop expected writes and the cache should then be clean */1953cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);1954KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));1955}19561957/*1958* bin file that contains a mix of packed and unpacked words.1959* payloads are in random offset order. Offsets that are on a packed boundary1960* are written as a packed block. Offsets that are not on a packed boundary1961* are written as a single unpacked word.1962*/1963static void bin_patch_mixed_packed_unpacked_random(struct kunit *test)1964{1965struct cs_dsp_test *priv = test->priv;1966const struct bin_test_param *param = test->param_value;1967static const u8 offset_words[] = {196858, 68, 50, 10, 44, 17, 74, 36, 8, 7, 49, 11, 78, 57, 65, 2,196948, 38, 22, 70, 77, 21, 61, 56, 75, 34, 27, 3, 31, 20, 43, 63,19705, 30, 32, 25, 33, 79, 29, 0, 37, 60, 69, 52, 13, 12, 24, 26,19714, 51, 76, 72, 16, 6, 39, 62, 15, 41, 28, 73, 53, 40, 45, 54,197214, 55, 46, 66, 64, 59, 23, 9, 67, 47, 19, 71, 35, 18, 42, 1,1973};1974struct {1975u32 packed[80][3];1976u32 unpacked[80];1977} *payload;1978u32 readback[3];1979unsigned int alg_base_words, patch_pos_words;1980unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;1981unsigned int reg_addr, payload_offset;1982int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);1983struct firmware *fw;1984int i;19851986payload = kunit_kmalloc(test, sizeof(*payload), GFP_KERNEL);1987KUNIT_ASSERT_NOT_NULL(test, payload);19881989get_random_bytes(payload->packed, sizeof(payload->packed));1990get_random_bytes(payload->unpacked, sizeof(payload->unpacked));19911992/* Create a patch entry for every offset in offset_words[] */1993for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {1994alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,1995bin_test_mock_algs[0].id,1996param->mem_type);1997/*1998* If the offset is on a packed boundary use a packed payload else1999* use an unpacked word2000*/2001patch_pos_words = alg_base_words + offset_words[i];2002if ((patch_pos_words % 4) == 0) {2003alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);2004patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);2005payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;2006cs_dsp_mock_bin_add_patch(priv->local->bin_builder,2007bin_test_mock_algs[0].id,2008bin_test_mock_algs[0].ver,2009param->mem_type,2010payload_offset,2011payload->packed[i],2012sizeof(payload->packed[i]));2013} else {2014payload_offset = offset_words[i] * 4;2015cs_dsp_mock_bin_add_patch(priv->local->bin_builder,2016bin_test_mock_algs[0].id,2017bin_test_mock_algs[0].ver,2018unpacked_mem_type,2019payload_offset,2020&payload->unpacked[i],2021sizeof(payload->unpacked[i]));2022}2023}20242025fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);2026KUNIT_ASSERT_EQ(test,2027cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",2028fw, "mock_bin", "misc"),20290);20302031/*2032* Readback the packed registers that should have been written.2033* Place the values into the expected location in readback[] so2034* that the content of readback[] should match payload->packed[]2035*/2036for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {2037alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2038bin_test_mock_algs[0].id,2039param->mem_type);2040patch_pos_words = alg_base_words + offset_words[i];20412042/* Skip if the offset is not on a packed boundary */2043if ((patch_pos_words % 4) != 0)2044continue;20452046patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);20472048reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +2049(patch_pos_in_packed_regs * 4);20502051memset(readback, 0, sizeof(readback));2052KUNIT_EXPECT_EQ(test,2053regmap_raw_read(priv->dsp->regmap, reg_addr, readback,2054sizeof(readback)),20550);2056KUNIT_EXPECT_MEMEQ(test, readback, payload->packed[i], sizeof(payload->packed[i]));20572058/* Drop expected writes from the cache */2059cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->packed[i]));2060}20612062/*2063* Readback the unpacked registers that should have been written.2064* Place the values into the expected location in readback[] so2065* that the content of readback[] should match payload->unpacked[]2066*/2067for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {2068alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2069bin_test_mock_algs[0].id,2070unpacked_mem_type);20712072patch_pos_words = alg_base_words + offset_words[i];20732074/* Skip if the offset is on a packed boundary */2075if ((patch_pos_words % 4) == 0)2076continue;20772078reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +2079((patch_pos_words) * 4);20802081readback[0] = 0;2082KUNIT_EXPECT_EQ(test,2083regmap_raw_read(priv->dsp->regmap, reg_addr,2084&readback[0], sizeof(readback[0])),20850);2086KUNIT_EXPECT_EQ(test, readback[0], payload->unpacked[i]);20872088/* Drop expected writes from the cache */2089cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->unpacked[i]));2090}20912092/* Drop expected writes and the cache should then be clean */2093cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);2094KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));2095}20962097/* Bin file with name and multiple info blocks */2098static void bin_patch_name_and_info(struct kunit *test)2099{2100struct cs_dsp_test *priv = test->priv;2101unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);2102u32 reg_val, payload_data;2103char *infobuf;2104unsigned int alg_base_words, reg_addr;2105struct firmware *fw;21062107get_random_bytes(&payload_data, sizeof(payload_data));21082109alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,2110bin_test_mock_algs[0].id,2111WMFW_ADSP2_YM);21122113/* Add a name block and info block */2114cs_dsp_mock_bin_add_name(priv->local->bin_builder, "The name");2115cs_dsp_mock_bin_add_info(priv->local->bin_builder, "Some info");21162117/* Add a big block of info */2118infobuf = kunit_kzalloc(test, 512, GFP_KERNEL);2119KUNIT_ASSERT_NOT_ERR_OR_NULL(test, infobuf);21202121for (; strlcat(infobuf, "Waffle{Blah}\n", 512) < 512; )2122;21232124cs_dsp_mock_bin_add_info(priv->local->bin_builder, infobuf);21252126/* Add a patch */2127cs_dsp_mock_bin_add_patch(priv->local->bin_builder,2128bin_test_mock_algs[0].id,2129bin_test_mock_algs[0].ver,2130WMFW_ADSP2_YM,21310,2132&payload_data, sizeof(payload_data));21332134fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);2135KUNIT_ASSERT_EQ(test,2136cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",2137fw, "mock_bin", "misc"),21380);21392140/* Content of registers should match payload_data */2141reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);2142reg_addr += alg_base_words * reg_inc_per_word;2143reg_val = 0;2144KUNIT_EXPECT_EQ(test,2145regmap_raw_read(priv->dsp->regmap, reg_addr,2146®_val, sizeof(reg_val)),21470);2148KUNIT_EXPECT_EQ(test, reg_val, payload_data);2149}21502151static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp)2152{2153struct cs_dsp_test *priv;2154struct cs_dsp_mock_xm_header *xm_hdr;2155struct device *test_dev;2156int ret;21572158priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);2159if (!priv)2160return -ENOMEM;21612162priv->local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);2163if (!priv->local)2164return -ENOMEM;21652166priv->test = test;2167priv->dsp = dsp;2168test->priv = priv;21692170/* Create dummy struct device */2171test_dev = kunit_device_register(test, "cs_dsp_test_drv");2172if (IS_ERR(test_dev))2173return PTR_ERR(test_dev);21742175dsp->dev = get_device(test_dev);2176if (!dsp->dev)2177return -ENODEV;21782179ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);2180if (ret)2181return ret;21822183dev_set_drvdata(dsp->dev, priv);21842185/* Allocate regmap */2186ret = cs_dsp_mock_regmap_init(priv);2187if (ret)2188return ret;21892190/* Create an XM header */2191xm_hdr = cs_dsp_create_mock_xm_header(priv,2192bin_test_mock_algs,2193ARRAY_SIZE(bin_test_mock_algs));2194KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_hdr);2195ret = cs_dsp_mock_xm_header_write_to_regmap(xm_hdr);2196KUNIT_ASSERT_EQ(test, ret, 0);21972198priv->local->bin_builder =2199cs_dsp_mock_bin_init(priv, 1,2200cs_dsp_mock_xm_header_get_fw_version(xm_hdr));2201KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->local->bin_builder);22022203/* We must provide a dummy wmfw to load */2204priv->local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, -1);2205priv->local->wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);22062207dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);2208KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);22092210switch (dsp->type) {2211case WMFW_ADSP2:2212ret = cs_dsp_adsp2_init(dsp);2213break;2214case WMFW_HALO:2215ret = cs_dsp_halo_init(dsp);2216break;2217default:2218KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);2219return -EINVAL;2220}22212222if (ret)2223return ret;22242225/* Automatically call cs_dsp_remove() when test case ends */2226return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);2227}22282229static int cs_dsp_bin_test_halo_init(struct kunit *test)2230{2231struct cs_dsp *dsp;22322233/* Fill in cs_dsp and initialize */2234dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);2235if (!dsp)2236return -ENOMEM;22372238dsp->num = 1;2239dsp->type = WMFW_HALO;2240dsp->mem = cs_dsp_mock_halo_dsp1_regions;2241dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);2242dsp->base = cs_dsp_mock_halo_core_base;2243dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;22442245return cs_dsp_bin_test_common_init(test, dsp);2246}22472248static int cs_dsp_bin_test_adsp2_32bit_init(struct kunit *test)2249{2250struct cs_dsp *dsp;22512252/* Fill in cs_dsp and initialize */2253dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);2254if (!dsp)2255return -ENOMEM;22562257dsp->num = 1;2258dsp->type = WMFW_ADSP2;2259dsp->rev = 1;2260dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;2261dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);2262dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;22632264return cs_dsp_bin_test_common_init(test, dsp);2265}22662267static int cs_dsp_bin_test_adsp2_16bit_init(struct kunit *test)2268{2269struct cs_dsp *dsp;22702271/* Fill in cs_dsp and initialize */2272dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);2273if (!dsp)2274return -ENOMEM;22752276dsp->num = 1;2277dsp->type = WMFW_ADSP2;2278dsp->rev = 0;2279dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;2280dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);2281dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;22822283return cs_dsp_bin_test_common_init(test, dsp);2284}22852286/* Parameterize on choice of XM or YM with a range of word offsets */2287static const struct bin_test_param x_or_y_and_offset_param_cases[] = {2288{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0 },2289{ .mem_type = WMFW_ADSP2_XM, .offset_words = 1 },2290{ .mem_type = WMFW_ADSP2_XM, .offset_words = 2 },2291{ .mem_type = WMFW_ADSP2_XM, .offset_words = 3 },2292{ .mem_type = WMFW_ADSP2_XM, .offset_words = 4 },2293{ .mem_type = WMFW_ADSP2_XM, .offset_words = 23 },2294{ .mem_type = WMFW_ADSP2_XM, .offset_words = 22 },2295{ .mem_type = WMFW_ADSP2_XM, .offset_words = 21 },2296{ .mem_type = WMFW_ADSP2_XM, .offset_words = 20 },22972298{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0 },2299{ .mem_type = WMFW_ADSP2_YM, .offset_words = 1 },2300{ .mem_type = WMFW_ADSP2_YM, .offset_words = 2 },2301{ .mem_type = WMFW_ADSP2_YM, .offset_words = 3 },2302{ .mem_type = WMFW_ADSP2_YM, .offset_words = 4 },2303{ .mem_type = WMFW_ADSP2_YM, .offset_words = 23 },2304{ .mem_type = WMFW_ADSP2_YM, .offset_words = 22 },2305{ .mem_type = WMFW_ADSP2_YM, .offset_words = 21 },2306{ .mem_type = WMFW_ADSP2_YM, .offset_words = 20 },2307};23082309/* Parameterize on ZM with a range of word offsets */2310static const struct bin_test_param z_and_offset_param_cases[] = {2311{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 0 },2312{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 1 },2313{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 2 },2314{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 3 },2315{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 4 },2316{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 23 },2317{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 22 },2318{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 21 },2319{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 20 },2320};23212322/* Parameterize on choice of packed XM or YM with a range of word offsets */2323static const struct bin_test_param packed_x_or_y_and_offset_param_cases[] = {2324{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0 },2325{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 4 },2326{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 8 },2327{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 12 },23282329{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0 },2330{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 4 },2331{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 8 },2332{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 12 },2333};23342335static void x_or_y_or_z_and_offset_param_desc(const struct bin_test_param *param,2336char *desc)2337{2338snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s@%u",2339cs_dsp_mem_region_name(param->mem_type),2340param->offset_words);2341}23422343KUNIT_ARRAY_PARAM(x_or_y_and_offset,2344x_or_y_and_offset_param_cases,2345x_or_y_or_z_and_offset_param_desc);23462347KUNIT_ARRAY_PARAM(z_and_offset,2348z_and_offset_param_cases,2349x_or_y_or_z_and_offset_param_desc);23502351KUNIT_ARRAY_PARAM(packed_x_or_y_and_offset,2352packed_x_or_y_and_offset_param_cases,2353x_or_y_or_z_and_offset_param_desc);23542355/* Parameterize on choice of packed XM or YM */2356static const struct bin_test_param packed_x_or_y_param_cases[] = {2357{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0 },2358{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0 },2359};23602361static void x_or_y_or_z_param_desc(const struct bin_test_param *param,2362char *desc)2363{2364snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", cs_dsp_mem_region_name(param->mem_type));2365}23662367KUNIT_ARRAY_PARAM(packed_x_or_y, packed_x_or_y_param_cases, x_or_y_or_z_param_desc);23682369static const struct bin_test_param offset_param_cases[] = {2370{ .offset_words = 0 },2371{ .offset_words = 1 },2372{ .offset_words = 2 },2373{ .offset_words = 3 },2374{ .offset_words = 4 },2375{ .offset_words = 23 },2376{ .offset_words = 22 },2377{ .offset_words = 21 },2378{ .offset_words = 20 },2379};23802381static void offset_param_desc(const struct bin_test_param *param, char *desc)2382{2383snprintf(desc, KUNIT_PARAM_DESC_SIZE, "@%u", param->offset_words);2384}23852386KUNIT_ARRAY_PARAM(offset, offset_param_cases, offset_param_desc);23872388static const struct bin_test_param alg_param_cases[] = {2389{ .alg_idx = 0 },2390{ .alg_idx = 1 },2391{ .alg_idx = 2 },2392{ .alg_idx = 3 },2393};23942395static void alg_param_desc(const struct bin_test_param *param, char *desc)2396{2397WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));23982399snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg[%u] (%#x)",2400param->alg_idx, bin_test_mock_algs[param->alg_idx].id);2401}24022403KUNIT_ARRAY_PARAM(alg, alg_param_cases, alg_param_desc);24042405static const struct bin_test_param x_or_y_and_alg_param_cases[] = {2406{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 0 },2407{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 1 },2408{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 2 },2409{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 3 },24102411{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 0 },2412{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 1 },2413{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 2 },2414{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 3 },2415};24162417static void x_or_y_or_z_and_alg_param_desc(const struct bin_test_param *param, char *desc)2418{2419WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));24202421snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s alg[%u] (%#x)",2422cs_dsp_mem_region_name(param->mem_type),2423param->alg_idx, bin_test_mock_algs[param->alg_idx].id);2424}24252426KUNIT_ARRAY_PARAM(x_or_y_and_alg, x_or_y_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);24272428static const struct bin_test_param z_and_alg_param_cases[] = {2429{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 0 },2430{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 1 },2431{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 2 },2432{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 3 },2433};24342435KUNIT_ARRAY_PARAM(z_and_alg, z_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);24362437static const struct bin_test_param packed_x_or_y_and_alg_param_cases[] = {2438{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 0 },2439{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 1 },2440{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 2 },2441{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 3 },24422443{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 0 },2444{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 1 },2445{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 2 },2446{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 3 },2447};24482449KUNIT_ARRAY_PARAM(packed_x_or_y_and_alg, packed_x_or_y_and_alg_param_cases,2450x_or_y_or_z_and_alg_param_desc);24512452static struct kunit_case cs_dsp_bin_test_cases_halo[] = {2453/* Unpacked memory */2454KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),2455KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),2456KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),2457KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),2458KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),2459KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),2460KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),2461KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),2462KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),24632464/* Packed memory tests */2465KUNIT_CASE_PARAM(bin_patch_1_packed,2466packed_x_or_y_and_offset_gen_params),2467KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,2468packed_x_or_y_and_offset_gen_params),2469KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,2470packed_x_or_y_and_offset_gen_params),2471KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,2472packed_x_or_y_and_offset_gen_params),2473KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,2474packed_x_or_y_and_offset_gen_params),2475KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,2476packed_x_or_y_and_offset_gen_params),2477KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,2478packed_x_or_y_and_offset_gen_params),2479KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,2480packed_x_or_y_and_offset_gen_params),2481KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,2482packed_x_or_y_and_offset_gen_params),2483KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,2484packed_x_or_y_and_offset_gen_params),2485KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,2486packed_x_or_y_and_offset_gen_params),2487KUNIT_CASE_PARAM(bin_patch_multi_onepacked,2488packed_x_or_y_and_offset_gen_params),2489KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,2490packed_x_or_y_and_offset_gen_params),2491KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, offset_gen_params),2492KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_gen_params),2493KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,2494packed_x_or_y_and_alg_gen_params),2495KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,2496packed_x_or_y_and_offset_gen_params),2497KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,2498packed_x_or_y_and_offset_gen_params),2499KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,2500packed_x_or_y_gen_params),25012502KUNIT_CASE(bin_patch_name_and_info),25032504{ } /* terminator */2505};25062507static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {2508/* XM and YM */2509KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),2510KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),2511KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),2512KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),2513KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),2514KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),2515KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),25162517/* ZM */2518KUNIT_CASE_PARAM(bin_patch_one_word, z_and_offset_gen_params),2519KUNIT_CASE_PARAM(bin_patch_one_multiword, z_and_offset_gen_params),2520KUNIT_CASE_PARAM(bin_patch_multi_oneword, z_and_offset_gen_params),2521KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, z_and_offset_gen_params),2522KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, z_and_alg_gen_params),2523KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, z_and_offset_gen_params),2524KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, z_and_offset_gen_params),25252526/* Other */2527KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),2528KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),25292530KUNIT_CASE(bin_patch_name_and_info),25312532{ } /* terminator */2533};25342535static struct kunit_suite cs_dsp_bin_test_halo = {2536.name = "cs_dsp_bin_halo",2537.init = cs_dsp_bin_test_halo_init,2538.test_cases = cs_dsp_bin_test_cases_halo,2539};25402541static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {2542.name = "cs_dsp_bin_adsp2_32bit",2543.init = cs_dsp_bin_test_adsp2_32bit_init,2544.test_cases = cs_dsp_bin_test_cases_adsp2,2545};25462547static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {2548.name = "cs_dsp_bin_adsp2_16bit",2549.init = cs_dsp_bin_test_adsp2_16bit_init,2550.test_cases = cs_dsp_bin_test_cases_adsp2,2551};25522553kunit_test_suites(&cs_dsp_bin_test_halo,2554&cs_dsp_bin_test_adsp2_32bit,2555&cs_dsp_bin_test_adsp2_16bit);255625572558