Re: [PATCH v2 3/3] tests/qtest: add test for K230 IOMUX
Chao Liu <[email protected]>
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Jul 14, 2026 at 06:22:02PM +0800, Kangjie Huang wrote: > 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 ++++++++++++++++++++++++++++++++++ k230-iomux-test.c needs to be added to MAINTAINERS. > 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); Please use a separate mask in the test. Reusing the implementation’s mask could let the test pass even if the mask is wrong. A short comment explaining the mask would also be helpful. /* Bits 13:0 are RW; bits 30:14 are reserved; bit 31 (DI) is RO. */ #define K230_IOMUX_EXPECTED_WRITABLE_MASK 0x00003fff [...] g_assert_cmphex(qtest_readl(qts, K230_IOMUX_IO0), ==, K230_IOMUX_EXPECTED_WRITABLE_MASK); Thanks, Chao > + 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 >