Path: blob/master/drivers/firmware/cirrus/test/cs_dsp_mock_regmap.c
26444 views
// SPDX-License-Identifier: GPL-2.0-only1//2// Mock regmap for cs_dsp KUnit tests.3//4// Copyright (C) 2024 Cirrus Logic, Inc. and5// Cirrus Logic International Semiconductor Ltd.67#include <kunit/test.h>8#include <linux/firmware/cirrus/cs_dsp.h>9#include <linux/firmware/cirrus/cs_dsp_test_utils.h>10#include <linux/firmware/cirrus/wmfw.h>11#include <linux/regmap.h>1213static int cs_dsp_mock_regmap_read(void *context, const void *reg_buf,14const size_t reg_size, void *val_buf,15size_t val_size)16{17struct cs_dsp_test *priv = context;1819/* Should never get here because the regmap is cache-only */20KUNIT_FAIL(priv->test, "Unexpected bus read @%#x", *(u32 *)reg_buf);2122return -EIO;23}2425static int cs_dsp_mock_regmap_gather_write(void *context,26const void *reg_buf, size_t reg_size,27const void *val_buf, size_t val_size)28{29struct cs_dsp_test *priv = context;3031priv->saw_bus_write = true;3233/* Should never get here because the regmap is cache-only */34KUNIT_FAIL(priv->test, "Unexpected bus gather_write @%#x", *(u32 *)reg_buf);3536return -EIO;37}3839static int cs_dsp_mock_regmap_write(void *context, const void *val_buf, size_t val_size)40{41struct cs_dsp_test *priv = context;4243priv->saw_bus_write = true;4445/* Should never get here because the regmap is cache-only */46KUNIT_FAIL(priv->test, "Unexpected bus write @%#x", *(u32 *)val_buf);4748return -EIO;49}5051static const struct regmap_bus cs_dsp_mock_regmap_bus = {52.read = cs_dsp_mock_regmap_read,53.write = cs_dsp_mock_regmap_write,54.gather_write = cs_dsp_mock_regmap_gather_write,55.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,56.val_format_endian_default = REGMAP_ENDIAN_LITTLE,57};5859static const struct reg_default adsp2_32bit_register_defaults[] = {60{ 0xffe00, 0x0000 }, /* CONTROL */61{ 0xffe02, 0x0000 }, /* CLOCKING */62{ 0xffe04, 0x0001 }, /* STATUS1: RAM_RDY=1 */63{ 0xffe30, 0x0000 }, /* WDMW_CONFIG_1 */64{ 0xffe32, 0x0000 }, /* WDMA_CONFIG_2 */65{ 0xffe34, 0x0000 }, /* RDMA_CONFIG_1 */66{ 0xffe40, 0x0000 }, /* SCRATCH_0_1 */67{ 0xffe42, 0x0000 }, /* SCRATCH_2_3 */68};6970static const struct regmap_range adsp2_32bit_registers[] = {71regmap_reg_range(0x80000, 0x88ffe), /* PM */72regmap_reg_range(0xa0000, 0xa9ffe), /* XM */73regmap_reg_range(0xc0000, 0xc1ffe), /* YM */74regmap_reg_range(0xe0000, 0xe1ffe), /* ZM */75regmap_reg_range(0xffe00, 0xffe7c), /* CORE CTRL */76};7778const unsigned int cs_dsp_mock_adsp2_32bit_sysbase = 0xffe00;79EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_adsp2_32bit_sysbase, "FW_CS_DSP_KUNIT_TEST_UTILS");8081static const struct regmap_access_table adsp2_32bit_rw = {82.yes_ranges = adsp2_32bit_registers,83.n_yes_ranges = ARRAY_SIZE(adsp2_32bit_registers),84};8586static const struct regmap_config cs_dsp_mock_regmap_adsp2_32bit = {87.reg_bits = 32,88.val_bits = 32,89.reg_stride = 2,90.reg_format_endian = REGMAP_ENDIAN_LITTLE,91.val_format_endian = REGMAP_ENDIAN_BIG,92.wr_table = &adsp2_32bit_rw,93.rd_table = &adsp2_32bit_rw,94.max_register = 0xffe7c,95.reg_defaults = adsp2_32bit_register_defaults,96.num_reg_defaults = ARRAY_SIZE(adsp2_32bit_register_defaults),97.cache_type = REGCACHE_MAPLE,98};99100static const struct reg_default adsp2_16bit_register_defaults[] = {101{ 0x1100, 0x0000 }, /* CONTROL */102{ 0x1101, 0x0000 }, /* CLOCKING */103{ 0x1104, 0x0001 }, /* STATUS1: RAM_RDY=1 */104{ 0x1130, 0x0000 }, /* WDMW_CONFIG_1 */105{ 0x1131, 0x0000 }, /* WDMA_CONFIG_2 */106{ 0x1134, 0x0000 }, /* RDMA_CONFIG_1 */107{ 0x1140, 0x0000 }, /* SCRATCH_0 */108{ 0x1141, 0x0000 }, /* SCRATCH_1 */109{ 0x1142, 0x0000 }, /* SCRATCH_2 */110{ 0x1143, 0x0000 }, /* SCRATCH_3 */111};112113static const struct regmap_range adsp2_16bit_registers[] = {114regmap_reg_range(0x001100, 0x001143), /* CORE CTRL */115regmap_reg_range(0x100000, 0x105fff), /* PM */116regmap_reg_range(0x180000, 0x1807ff), /* ZM */117regmap_reg_range(0x190000, 0x1947ff), /* XM */118regmap_reg_range(0x1a8000, 0x1a97ff), /* YM */119};120121const unsigned int cs_dsp_mock_adsp2_16bit_sysbase = 0x001100;122EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_adsp2_16bit_sysbase, "FW_CS_DSP_KUNIT_TEST_UTILS");123124static const struct regmap_access_table adsp2_16bit_rw = {125.yes_ranges = adsp2_16bit_registers,126.n_yes_ranges = ARRAY_SIZE(adsp2_16bit_registers),127};128129static const struct regmap_config cs_dsp_mock_regmap_adsp2_16bit = {130.reg_bits = 32,131.val_bits = 16,132.reg_stride = 1,133.reg_format_endian = REGMAP_ENDIAN_LITTLE,134.val_format_endian = REGMAP_ENDIAN_BIG,135.wr_table = &adsp2_16bit_rw,136.rd_table = &adsp2_16bit_rw,137.max_register = 0x1a97ff,138.reg_defaults = adsp2_16bit_register_defaults,139.num_reg_defaults = ARRAY_SIZE(adsp2_16bit_register_defaults),140.cache_type = REGCACHE_MAPLE,141};142143static const struct reg_default halo_register_defaults[] = {144/* CORE */145{ 0x2b80010, 0 }, /* HALO_CORE_SOFT_RESET */146{ 0x2b805c0, 0 }, /* HALO_SCRATCH1 */147{ 0x2b805c8, 0 }, /* HALO_SCRATCH2 */148{ 0x2b805d0, 0 }, /* HALO_SCRATCH3 */149{ 0x2b805c8, 0 }, /* HALO_SCRATCH4 */150{ 0x2bc1000, 0 }, /* HALO_CCM_CORE_CONTROL */151{ 0x2bc7000, 0 }, /* HALO_WDT_CONTROL */152153/* SYSINFO */154{ 0x25e2040, 0 }, /* HALO_AHBM_WINDOW_DEBUG_0 */155{ 0x25e2044, 0 }, /* HALO_AHBM_WINDOW_DEBUG_1 */156};157158static const struct regmap_range halo_readable_registers[] = {159regmap_reg_range(0x2000000, 0x2005fff), /* XM_PACKED */160regmap_reg_range(0x25e0000, 0x25e004f), /* SYSINFO */161regmap_reg_range(0x25e2000, 0x25e2047), /* SYSINFO */162regmap_reg_range(0x2800000, 0x2807fff), /* XM */163regmap_reg_range(0x2b80000, 0x2bc700b), /* CORE CTRL */164regmap_reg_range(0x2c00000, 0x2c047f3), /* YM_PACKED */165regmap_reg_range(0x3400000, 0x3405ff7), /* YM */166regmap_reg_range(0x3800000, 0x3804fff), /* PM_PACKED */167};168169static const struct regmap_range halo_writeable_registers[] = {170regmap_reg_range(0x2000000, 0x2005fff), /* XM_PACKED */171regmap_reg_range(0x2800000, 0x2807fff), /* XM */172regmap_reg_range(0x2b80000, 0x2bc700b), /* CORE CTRL */173regmap_reg_range(0x2c00000, 0x2c047f3), /* YM_PACKED */174regmap_reg_range(0x3400000, 0x3405ff7), /* YM */175regmap_reg_range(0x3800000, 0x3804fff), /* PM_PACKED */176};177178const unsigned int cs_dsp_mock_halo_core_base = 0x2b80000;179EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_halo_core_base, "FW_CS_DSP_KUNIT_TEST_UTILS");180181const unsigned int cs_dsp_mock_halo_sysinfo_base = 0x25e0000;182EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_halo_sysinfo_base, "FW_CS_DSP_KUNIT_TEST_UTILS");183184static const struct regmap_access_table halo_readable = {185.yes_ranges = halo_readable_registers,186.n_yes_ranges = ARRAY_SIZE(halo_readable_registers),187};188189static const struct regmap_access_table halo_writeable = {190.yes_ranges = halo_writeable_registers,191.n_yes_ranges = ARRAY_SIZE(halo_writeable_registers),192};193194static const struct regmap_config cs_dsp_mock_regmap_halo = {195.reg_bits = 32,196.val_bits = 32,197.reg_stride = 4,198.reg_format_endian = REGMAP_ENDIAN_LITTLE,199.val_format_endian = REGMAP_ENDIAN_BIG,200.wr_table = &halo_writeable,201.rd_table = &halo_readable,202.max_register = 0x3804ffc,203.reg_defaults = halo_register_defaults,204.num_reg_defaults = ARRAY_SIZE(halo_register_defaults),205.cache_type = REGCACHE_MAPLE,206};207208/**209* cs_dsp_mock_regmap_drop_range() - drop a range of registers from the cache.210*211* @priv: Pointer to struct cs_dsp_test object.212* @first_reg: Address of first register to drop.213* @last_reg: Address of last register to drop.214*/215void cs_dsp_mock_regmap_drop_range(struct cs_dsp_test *priv,216unsigned int first_reg, unsigned int last_reg)217{218regcache_drop_region(priv->dsp->regmap, first_reg, last_reg);219}220EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_regmap_drop_range, "FW_CS_DSP_KUNIT_TEST_UTILS");221222/**223* cs_dsp_mock_regmap_drop_regs() - drop a number of registers from the cache.224*225* @priv: Pointer to struct cs_dsp_test object.226* @first_reg: Address of first register to drop.227* @num_regs: Number of registers to drop.228*/229void cs_dsp_mock_regmap_drop_regs(struct cs_dsp_test *priv,230unsigned int first_reg, size_t num_regs)231{232int stride = regmap_get_reg_stride(priv->dsp->regmap);233unsigned int last = first_reg + (stride * (num_regs - 1));234235cs_dsp_mock_regmap_drop_range(priv, first_reg, last);236}237EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_regmap_drop_regs, "FW_CS_DSP_KUNIT_TEST_UTILS");238239/**240* cs_dsp_mock_regmap_drop_bytes() - drop a number of bytes from the cache.241*242* @priv: Pointer to struct cs_dsp_test object.243* @first_reg: Address of first register to drop.244* @num_bytes: Number of bytes to drop from the cache. Will be rounded245* down to a whole number of registers. Trailing bytes that246* are not a multiple of the register size will not be dropped.247* (This is intended to help detect math errors in test code.)248*/249void cs_dsp_mock_regmap_drop_bytes(struct cs_dsp_test *priv,250unsigned int first_reg, size_t num_bytes)251{252size_t num_regs = num_bytes / regmap_get_val_bytes(priv->dsp->regmap);253254cs_dsp_mock_regmap_drop_regs(priv, first_reg, num_regs);255}256EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_regmap_drop_bytes, "FW_CS_DSP_KUNIT_TEST_UTILS");257258/**259* cs_dsp_mock_regmap_drop_system_regs() - Drop DSP system registers from the cache.260*261* @priv: Pointer to struct cs_dsp_test object.262*263* Drops all DSP system registers from the regmap cache.264*/265void cs_dsp_mock_regmap_drop_system_regs(struct cs_dsp_test *priv)266{267switch (priv->dsp->type) {268case WMFW_ADSP2:269if (priv->dsp->base) {270regcache_drop_region(priv->dsp->regmap,271priv->dsp->base,272priv->dsp->base + 0x7c);273}274return;275case WMFW_HALO:276if (priv->dsp->base) {277regcache_drop_region(priv->dsp->regmap,278priv->dsp->base,279priv->dsp->base + 0x47000);280}281282/* sysinfo registers are read-only so don't drop them */283return;284default:285return;286}287}288EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_regmap_drop_system_regs, "FW_CS_DSP_KUNIT_TEST_UTILS");289290/**291* cs_dsp_mock_regmap_is_dirty() - Test for dirty registers in the cache.292*293* @priv: Pointer to struct cs_dsp_test object.294* @drop_system_regs: If true the DSP system regs will be dropped from295* the cache before checking for dirty.296*297* All registers that are expected to be written must have been dropped298* from the cache (DSP system registers can be dropped by passing299* drop_system_regs == true). If any unexpected registers were written300* there will still be dirty entries in the cache and a cache sync will301* cause a write.302*303* Returns: true if there were dirty entries, false if not.304*/305bool cs_dsp_mock_regmap_is_dirty(struct cs_dsp_test *priv, bool drop_system_regs)306{307if (drop_system_regs)308cs_dsp_mock_regmap_drop_system_regs(priv);309310priv->saw_bus_write = false;311regcache_cache_only(priv->dsp->regmap, false);312regcache_sync(priv->dsp->regmap);313regcache_cache_only(priv->dsp->regmap, true);314315return priv->saw_bus_write;316}317EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_regmap_is_dirty, "FW_CS_DSP_KUNIT_TEST_UTILS");318319/**320* cs_dsp_mock_regmap_init() - Initialize a mock regmap.321*322* @priv: Pointer to struct cs_dsp_test object. This must have a323* valid pointer to a struct cs_dsp in which the type and324* rev fields are set to the type of DSP to be simulated.325*326* On success the priv->dsp->regmap will point to the created327* regmap instance.328*329* Return: zero on success, else negative error code.330*/331int cs_dsp_mock_regmap_init(struct cs_dsp_test *priv)332{333const struct regmap_config *config;334int ret;335336switch (priv->dsp->type) {337case WMFW_HALO:338config = &cs_dsp_mock_regmap_halo;339break;340case WMFW_ADSP2:341if (priv->dsp->rev == 0)342config = &cs_dsp_mock_regmap_adsp2_16bit;343else344config = &cs_dsp_mock_regmap_adsp2_32bit;345break;346default:347config = NULL;348break;349}350351priv->dsp->regmap = devm_regmap_init(priv->dsp->dev,352&cs_dsp_mock_regmap_bus,353priv,354config);355if (IS_ERR(priv->dsp->regmap)) {356ret = PTR_ERR(priv->dsp->regmap);357kunit_err(priv->test, "Failed to allocate register map: %d\n", ret);358return ret;359}360361/* Put regmap in cache-only so it accumulates the writes done by cs_dsp */362regcache_cache_only(priv->dsp->regmap, true);363364return 0;365}366EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_regmap_init, "FW_CS_DSP_KUNIT_TEST_UTILS");367368369