Cover the 64 documented reset values, writable field storage and masking, read-modify-write accesses, the final IO63 register, reserved offsets, and system reset.
Signed-off-by: Kangjie Huang <[email protected]> --- tests/qtest/k230-iomux-test.c | 155 ++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 5 +- 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/k230-iomux-test.c diff --git a/tests/qtest/k230-iomux-test.c b/tests/qtest/k230-iomux-test.c new file mode 100644 index 0000000000..39653cf832 --- /dev/null +++ b/tests/qtest/k230-iomux-test.c @@ -0,0 +1,155 @@ +/* + * QTest testcase for Kendryte K230 IOMUX + * + * Copyright (c) 2026 Kangjie Huang <[email protected]> + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Provides test coverage for the Function IO configuration registers. + * + * K230 Technical Reference Manual V0.3.1 (2024-11-18): + * https://github.com/revyos/external-docs/blob/master/K230/en-us/K230_Technical_Reference_Manual_V0.3.1_20241118.pdf + * + * For more information, see <https://www.kendryte.com/en/proDetail/230> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "hw/misc/k230_iomux.h" + +#define K230_IOMUX_BASE 0x91105000 +#define K230_IOMUX_IO0 (K230_IOMUX_BASE + 0x00) +#define K230_IOMUX_IO1 (K230_IOMUX_BASE + 0x04) +#define K230_IOMUX_IO63 (K230_IOMUX_BASE + 0xfc) +#define K230_IOMUX_RESERVED_FIRST (K230_IOMUX_BASE + 0x100) +#define K230_IOMUX_RESERVED_LAST \ + (K230_IOMUX_BASE + K230_IOMUX_MMIO_SIZE - 4) +#define K230_IOMUX_IO_SEL_MASK (0x7 << 11) +#define K230_IOMUX_IO_SEL(value) ((value) << 11) + +static const uint32_t k230_iomux_reset_values[K230_IOMUX_NUM_REGS] = { + 0x944, 0x944, 0x929, 0x908, 0x888, 0x908, 0x948, 0x890, + 0x890, 0x890, 0x910, 0x890, 0x890, 0x8a9, 0xa9e, 0xabf, + 0xb9e, 0xb9e, 0xb9e, 0xb9e, 0xb9e, 0xb9e, 0xb9e, 0xb9e, + 0xb1e, 0xa90, 0xabf, 0xb9e, 0xb9e, 0xb9e, 0xb9e, 0xb9e, + 0xbd0, 0xbd0, 0xbd0, 0xbd0, 0xbd0, 0xbd0, 0x890, 0x910, + 0x890, 0x910, 0x890, 0x910, 0x890, 0x910, 0x890, 0x910, + 0x890, 0x910, 0x890, 0x910, 0x890, 0x910, 0x89e, 0x89f, + 0x99e, 0x99e, 0x99e, 0x99e, 0x890, 0x890, 0x8a9, 0x8a9, +}; + +static void test_reset_values(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + for (size_t i = 0; i < G_N_ELEMENTS(k230_iomux_reset_values); i++) { + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_BASE + + i * sizeof(uint32_t)), ==, + k230_iomux_reset_values[i]); + } + + qtest_quit(qts); +} + +static void test_rw(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + qtest_writel(qts, K230_IOMUX_IO0, 0x00001234); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, 0x00001234); + + qtest_writel(qts, K230_IOMUX_IO1, 0x00002abc); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO1), ==, 0x00002abc); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, 0x00001234); + + qtest_quit(qts); +} + +static void test_write_mask(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + qtest_writel(qts, K230_IOMUX_IO0, UINT32_MAX); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, + K230_IOMUX_WRITABLE_MASK); + + qtest_quit(qts); +} + +static void test_rmw(void) +{ + QTestState *qts = qtest_init("-machine k230"); + uint32_t value; + + value = qtest_readl(qts, K230_IOMUX_IO0); + value = (value & ~K230_IOMUX_IO_SEL_MASK) | K230_IOMUX_IO_SEL(3); + qtest_writel(qts, K230_IOMUX_IO0, value); + + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, + (k230_iomux_reset_values[0] & + ~K230_IOMUX_IO_SEL_MASK) | K230_IOMUX_IO_SEL(3)); + + qtest_quit(qts); +} + +static void test_io63_rw(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + qtest_writel(qts, K230_IOMUX_IO63, 0x00000abc); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO63), ==, 0x00000abc); + + qtest_quit(qts); +} + +static void test_reserved_offsets(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + qtest_writel(qts, K230_IOMUX_RESERVED_FIRST, 0x00001234); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_RESERVED_FIRST), ==, 0); + + qtest_writel(qts, K230_IOMUX_RESERVED_LAST, 0x00002abc); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_RESERVED_LAST), ==, 0); + + qtest_quit(qts); +} + +static void test_reset_after_write(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + qtest_writel(qts, K230_IOMUX_IO0, 0x00001234); + qtest_writel(qts, K230_IOMUX_IO1, 0x00002abc); + qtest_writel(qts, K230_IOMUX_IO63, 0x00000abc); + + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, 0x00001234); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO1), ==, 0x00002abc); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO63), ==, 0x00000abc); + + qtest_system_reset(qts); + + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, + k230_iomux_reset_values[0]); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO1), ==, + k230_iomux_reset_values[1]); + g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO63), ==, + k230_iomux_reset_values[63]); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/k230-iomux/reset", test_reset_values); + qtest_add_func("/k230-iomux/rw", test_rw); + qtest_add_func("/k230-iomux/write-mask", test_write_mask); + qtest_add_func("/k230-iomux/rmw", test_rmw); + qtest_add_func("/k230-iomux/io63-rw", test_io63_rw); + qtest_add_func("/k230-iomux/reserved-offsets", test_reserved_offsets); + qtest_add_func("/k230-iomux/reset-after-write", test_reset_after_write); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 56ff860e21..cb8001ecbf 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -297,7 +297,10 @@ qtests_riscv64 = ['riscv-csr-test'] + \ (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and config_all_devices.has_key('CONFIG_RISCV_IOMMU') ? ['iommu-riscv-test'] : []) + \ - (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test'] : []) + (config_all_devices.has_key('CONFIG_K230') ? [ + 'k230-wdt-test', + 'k230-iomux-test', + ] : []) qtests_hexagon = ['boot-serial-test'] -- 2.43.0
