/* * Test method is: * * 1) Create a mock regmap in cache-only mode so that all writes will be cached. * 2) Create a XM header with an algorithm list in the cached regmap. * 3) Create dummy wmfw file to satisfy cs_dsp. * 4) Create bin file content. * 5) Call cs_dsp_power_up() with the bin file. * 6) Readback the cached value of registers that should have been written and * check they have the correct value. * 7) All the registers that are expected to have been written are dropped from * the cache (including the XM header). This should leave the cache clean. * 8) If the cache is still dirty there have been unexpected writes. * * There are multiple different schemes used for addressing across * ADSP2 and Halo Core DSPs: * * dsp words: The addressing scheme used by the DSP, pointers and lengths * in DSP memory use this. A memory region (XM, YM, ZM) is * also required to create a unique DSP memory address. * registers: Addresses in the register map. Older ADSP2 devices have * 16-bit registers with an address stride of 1. Newer ADSP2 * devices have 32-bit registers with an address stride of 2. * Halo Core devices have 32-bit registers with a stride of 4. * unpacked: Registers that have a 1:1 mapping to DSP words * packed: Registers that pack multiple DSP words more efficiently into * multiple 32-bit registers. Because of this the relationship * between a packed _register_ address and the corresponding * _dsp word_ address is different from unpacked registers. * Packed registers can only be accessed as a group of * multiple registers, therefore can only read/write a group * of multiple DSP words. * Packed registers only exist on Halo Core DSPs. * * Addresses can also be relative to the start of an algorithm, and this * can be expressed in dsp words, register addresses, or bytes.
*/
/* * Convert number of DSP words to number of packed registers rounded * down to the nearest register. * There are 3 registers for every 4 packed words.
*/ staticunsignedint _num_words_to_num_packed_regs(unsignedint num_dsp_words)
{ return (num_dsp_words * 3) / 4;
}
/* bin file that patches a single DSP word */ staticvoid bin_patch_one_word(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
u32 reg_val, payload_data; unsignedint alg_base_words, reg_addr; struct firmware *fw;
/* Content of registers should match payload_data */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + param->offset_words) * reg_inc_per_word);
reg_val = 0;
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr,
®_val, sizeof(reg_val)),
0);
KUNIT_EXPECT_EQ(test, reg_val, payload_data);
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
/* Content of registers should match payload_data */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + param->offset_words) * reg_inc_per_word);
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
0);
KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_regmap_drop_range(priv, reg_addr,
reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* bin file with a multiple one-word payloads that patch consecutive words */ staticvoid bin_patch_multi_oneword(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
u32 payload_data[16], readback[16]; unsignedint alg_base_words, reg_addr; struct firmware *fw; int i;
/* Add one payload per word */ for (i = 0; i < ARRAY_SIZE(payload_data); ++i) {
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
param->mem_type,
(param->offset_words + i) * reg_inc_per_word,
&payload_data[i], sizeof(payload_data[i]));
}
/* Content of registers should match payload_data */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + param->offset_words) * reg_inc_per_word);
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
0);
KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
cs_dsp_mock_regmap_drop_range(priv, reg_addr,
reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file with a multiple one-word payloads that patch a block of consecutive * words but the payloads are not in address order.
*/ staticvoid bin_patch_multi_oneword_unordered(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
u32 payload_data[16], readback[16]; staticconst u8 word_order[] = { 10, 2, 12, 4, 0, 11, 6, 1, 3, 15, 5, 13, 8, 7, 9, 14 }; unsignedint alg_base_words, reg_addr; struct firmware *fw; int i;
/* Add one payload per word */ for (i = 0; i < ARRAY_SIZE(word_order); ++i) {
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
param->mem_type,
(param->offset_words + word_order[i]) *
reg_inc_per_word,
&payload_data[word_order[i]], sizeof(payload_data[0]));
}
/* Content of registers should match payload_data */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + param->offset_words) * reg_inc_per_word);
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
0);
KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
cs_dsp_mock_regmap_drop_range(priv, reg_addr,
reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file with a multiple one-word payloads. The payloads are not in address * order and collectively do not patch a contiguous block of memory.
*/ staticvoid bin_patch_multi_oneword_sparse_unordered(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); staticconst u8 word_offsets[] = {
11, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,
54, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,
29, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22
};
u32 payload_data[44]; unsignedint alg_base_words, reg_addr; struct firmware *fw;
u32 reg_val; int i;
/* Add one payload per word */ for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
param->mem_type,
word_offsets[i] * reg_inc_per_word,
&payload_data[i], sizeof(payload_data[i]));
}
/* Content of registers should match payload_data */ for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + word_offsets[i]) * reg_inc_per_word);
reg_val = 0;
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),
0);
KUNIT_EXPECT_MEMEQ(test, ®_val, &payload_data[i], sizeof(reg_val));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
}
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file that patches a single DSP word in each of the memory regions * of one algorithm.
*/ staticvoid bin_patch_one_word_multiple_mems(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); unsignedint alg_xm_base_words, alg_ym_base_words, alg_zm_base_words; unsignedint reg_addr;
u32 payload_data[3]; struct firmware *fw;
u32 reg_val;
/* Add words to XM, YM and ZM */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
WMFW_ADSP2_XM,
param->offset_words * reg_inc_per_word,
&payload_data[0], sizeof(payload_data[0]));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
}
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file that patches a single DSP word in multiple algorithms.
*/ staticvoid bin_patch_one_word_multiple_algs(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value;
u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)]; unsignedint alg_base_words; unsignedint reg_inc_per_word, reg_addr; struct firmware *fw;
u32 reg_val; int i;
/* Add one payload per algorithm */ for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
/* Content of registers should match payload_data */ for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
bin_test_mock_algs[i].id,
param->mem_type);
reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + param->offset_words) * reg_inc_per_word);
reg_val = 0;
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),
0);
KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
}
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file that patches a single DSP word in multiple algorithms. * The algorithms are not patched in the same order they appear in the XM header.
*/ staticvoid bin_patch_one_word_multiple_algs_unordered(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; staticconst u8 alg_order[] = { 3, 0, 2, 1 };
u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)]; unsignedint alg_base_words; unsignedint reg_inc_per_word, reg_addr; struct firmware *fw;
u32 reg_val; int i, alg_idx;
/* Add one payload per algorithm */ for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
alg_idx = alg_order[i];
reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
/* Content of registers should match payload_data */ for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
alg_idx = alg_order[i];
alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
bin_test_mock_algs[alg_idx].id,
param->mem_type);
reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
((alg_base_words + param->offset_words) * reg_inc_per_word);
reg_val = 0;
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, ®_val, sizeof(reg_val)),
0);
KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
}
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* bin file that patches a single packed block of DSP words */ staticvoid bin_patch_1_packed(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value;
u32 packed_payload[3], readback[3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round patch start word up to a packed boundary */
patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
/* Content of registers should match payload_data */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
(patch_pos_in_packed_regs * 4);
memset(readback, 0, sizeof(readback));
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
0);
KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that is one word longer than a packed block using one * packed block followed by one unpacked word.
*/ staticvoid bin_patch_1_packed_1_single_trailing(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[1], readback[3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round patch start word up to a packed boundary */
patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
/* ... and the unpacked word following that */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((patch_pos_words + 4) - alg_base_words) * 4,
unpacked_payload, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that is two words longer than a packed block using one * packed block followed by two blocks of one unpacked word.
*/ staticvoid bin_patch_1_packed_2_single_trailing(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payloads[2], readback[3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round patch start word up to a packed boundary */
patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
/* ... and the unpacked words following that */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((patch_pos_words + 4) - alg_base_words) * 4,
&unpacked_payloads[0], sizeof(unpacked_payloads[0]));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that is three words longer than a packed block using one * packed block followed by three blocks of one unpacked word.
*/ staticvoid bin_patch_1_packed_3_single_trailing(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payloads[3], readback[3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round patch start word up to a packed boundary */
patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
/* ... and the unpacked words following that */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((patch_pos_words + 4) - alg_base_words) * 4,
&unpacked_payloads[0], sizeof(unpacked_payloads[0]));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that is two words longer than a packed block using one * packed block followed by a block of two unpacked words.
*/ staticvoid bin_patch_1_packed_2_trailing(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[2], readback[3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round patch start word up to a packed boundary */
patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
/* ... and the unpacked words following that */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((patch_pos_words + 4) - alg_base_words) * 4,
unpacked_payload, sizeof(unpacked_payload));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that is three words longer than a packed block using one * packed block followed by a block of three unpacked words.
*/ staticvoid bin_patch_1_packed_3_trailing(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[3], readback[3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round patch start word up to a packed boundary */
patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
/* ... and the unpacked words following that */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((patch_pos_words + 4) - alg_base_words) * 4,
unpacked_payload, sizeof(unpacked_payload));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that starts one word before a packed boundary using one * unpacked word followed by one packed block.
*/ staticvoid bin_patch_1_single_leading_1_packed(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[1], readback[3]; unsignedint alg_base_words, packed_patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round packed start word up to a packed boundary and move to the next boundary */
packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
/* Patch the leading unpacked word */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((packed_patch_pos_words - 1) - alg_base_words) * 4,
unpacked_payload, sizeof(unpacked_payload)); /* ... then the packed block */
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
param->mem_type,
(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
&packed_payload, sizeof(packed_payload));
/* Content of packed registers should match packed_payload */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
(patch_pos_in_packed_regs * 4);
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
0);
KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
/* Content of unpacked registers should match unpacked_payload */
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
(packed_patch_pos_words - 1) * 4;
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(unpacked_payload)),
0);
KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that starts two words before a packed boundary using two * unpacked words followed by one packed block.
*/ staticvoid bin_patch_2_single_leading_1_packed(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[2], readback[3]; unsignedint alg_base_words, packed_patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round packed start word up to a packed boundary and move to the next boundary */
packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that starts two words before a packed boundary using one * block of two unpacked words followed by one packed block.
*/ staticvoid bin_patch_2_leading_1_packed(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[2], readback[3]; unsignedint alg_base_words, packed_patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round packed start word up to a packed boundary and move to the next boundary */
packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
/* Patch the leading unpacked words */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((packed_patch_pos_words - 2) - alg_base_words) * 4,
unpacked_payload, sizeof(unpacked_payload)); /* ... then the packed block */
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
param->mem_type,
(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
&packed_payload, sizeof(packed_payload));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that starts three words before a packed boundary using three * unpacked words followed by one packed block.
*/ staticvoid bin_patch_3_single_leading_1_packed(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[3], readback[3]; unsignedint alg_base_words, packed_patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round packed start word up to a packed boundary and move to the next boundary */
packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * Patch data that starts three words before a packed boundary using one * block of three unpacked words followed by one packed block.
*/ staticvoid bin_patch_3_leading_1_packed(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; unsignedint unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
u32 packed_payload[3], unpacked_payload[3], readback[3]; unsignedint alg_base_words, packed_patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint reg_addr; struct firmware *fw;
/* Round packed start word up to a packed boundary and move to the next boundary */
packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
/* Patch the leading unpacked words */
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
unpacked_mem_type,
((packed_patch_pos_words - 3) - alg_base_words) * 4,
unpacked_payload, sizeof(unpacked_payload)); /* ... then the packed block */
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
bin_test_mock_algs[param->alg_idx].id,
bin_test_mock_algs[param->alg_idx].ver,
param->mem_type,
(patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
&packed_payload, sizeof(packed_payload));
/* Drop expected writes from the cache */
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* bin file with a multiple payloads that each patch one packed block. */ staticvoid bin_patch_multi_onepacked(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value;
u32 packed_payloads[8][3], readback[8][3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint payload_offset; unsignedint reg_addr; struct firmware *fw; int i;
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file with a multiple payloads that each patch one packed block. * The payloads are not in address order.
*/ staticvoid bin_patch_multi_onepacked_unordered(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; staticconst u8 payload_order[] = { 4, 3, 6, 1, 0, 7, 5, 2 };
u32 packed_payloads[8][3], readback[8][3]; unsignedint alg_base_words, patch_pos_words; unsignedint alg_base_in_packed_regs, patch_pos_in_packed_regs; unsignedint payload_offset; unsignedint reg_addr; struct firmware *fw; int i;
/* Content in registers should match the order of data in packed_payloads */
patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
(patch_pos_in_packed_regs * 4);
memset(readback, 0, sizeof(readback));
KUNIT_EXPECT_EQ(test,
regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
0);
KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));
/* Drop expected writes and the cache should then be clean */
cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));
KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
}
/* * bin file with a multiple payloads that each patch one packed block. * The payloads are not in address order. The patched memory is not contiguous.
*/ staticvoid bin_patch_multi_onepacked_sparse_unordered(struct kunit *test)
{ struct cs_dsp_test *priv = test->priv; conststruct bin_test_param *param = test->param_value; staticconst u8 word_offsets[] = { 60, 24, 76, 4, 40, 52, 48, 36, 12 };
u32 packed_payloads[9][3], readback[3]; unsignedint alg_base_words, alg_base_in_packed_regs; unsignedint patch_pos_words, patch_pos_in_packed_regs, payload_offset; unsignedint reg_addr; struct firmware *fw; int i;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.