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
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.