All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] hw/riscv/k230: add IOMUX register block model
@ 2026-07-14 10:21 Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 1/3] hw/misc/k230_iomux: add Kendryte K230 IOMUX model Kangjie Huang
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Kangjie Huang @ 2026-07-14 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Chao Liu, Alistair Francis, Palmer Dabbelt, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Pierrick Bouvier,
	Paolo Bonzini, Fabiano Rosas, Laurent Vivier, Kangjie Huang

Add a SysBus model for the 64 K230 Function IO configuration registers
documented by the K230 Technical Reference Manual. The model retains the
writable configuration fields needed by the SDK U-Boot and Linux
read-modify-write paths.

The series adds the device model, wires it into the K230 SoC at
0x91105000, and adds qtest coverage.

Changes in v2:
- Split the device model, SoC wiring, and qtest coverage into separate
  patches.
- Removed redundant MMIO bounds, access-size, and alignment checks.
- Limited register storage to the 64 documented Function IO registers.
- Applied the documented 0x00003fff writable mask.
- Treated offsets 0x100 through 0x7ff as reserved.
- Added tests for write masking, read-modify-write accesses, IO63,
  reserved offsets, and system reset.

Tested with:
- qtest-riscv64/k230-iomux-test
- qtest-riscv64/k230-wdt-test
- SDK U-Boot smoke test, reaching the K230 prompt

v1:
https://lore.kernel.org/qemu-devel/20260710041845.67170-1-flamboyant.h.01@gmail.com/

Kangjie Huang (3):
  hw/misc/k230_iomux: add Kendryte K230 IOMUX model
  hw/riscv/k230: wire up the IOMUX device
  tests/qtest: add test for K230 IOMUX

 docs/system/riscv/k230.rst    |   1 +
 hw/misc/Kconfig               |   3 +
 hw/misc/k230_iomux.c          | 124 +++++++++++++++++++++++++++
 hw/misc/meson.build           |   2 +
 hw/misc/trace-events          |   4 +
 hw/riscv/Kconfig              |   1 +
 hw/riscv/k230.c               |  11 ++-
 include/hw/misc/k230_iomux.h  |  34 ++++++++
 include/hw/riscv/k230.h       |   2 +
 tests/qtest/k230-iomux-test.c | 155 ++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build       |   5 +-
 11 files changed, 338 insertions(+), 4 deletions(-)
 create mode 100644 hw/misc/k230_iomux.c
 create mode 100644 include/hw/misc/k230_iomux.h
 create mode 100644 tests/qtest/k230-iomux-test.c

-- 
2.43.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/3] hw/misc/k230_iomux: add Kendryte K230 IOMUX model
  2026-07-14 10:21 [PATCH v2 0/3] hw/riscv/k230: add IOMUX register block model Kangjie Huang
@ 2026-07-14 10:22 ` Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 2/3] hw/riscv/k230: wire up the IOMUX device Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 3/3] tests/qtest: add test for K230 IOMUX Kangjie Huang
  2 siblings, 0 replies; 4+ messages in thread
From: Kangjie Huang @ 2026-07-14 10:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Chao Liu, Alistair Francis, Palmer Dabbelt, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Pierrick Bouvier,
	Paolo Bonzini, Fabiano Rosas, Laurent Vivier, Kangjie Huang

Add a SysBus model for the 64 K230 Function IO configuration
registers documented by the K230 Technical Reference Manual.

Preserve the writable configuration fields across aligned 32-bit
accesses, apply the documented reset values, and ignore writes to
read-only and reserved fields. Offsets outside the documented register
list read as zero and ignore writes.

This provides the register behavior used by the Kendryte SDK U-Boot
pinctrl-single driver and Linux IOMUX configuration code.

Signed-off-by: Kangjie Huang <flamboyant.h.01@gmail.com>
---
 hw/misc/Kconfig              |   3 +
 hw/misc/k230_iomux.c         | 124 +++++++++++++++++++++++++++++++++++
 hw/misc/meson.build          |   2 +
 hw/misc/trace-events         |   4 ++
 include/hw/misc/k230_iomux.h |  34 ++++++++++
 5 files changed, 167 insertions(+)
 create mode 100644 hw/misc/k230_iomux.c
 create mode 100644 include/hw/misc/k230_iomux.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1543ee6653..573d24a9df 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -257,4 +257,7 @@ config XLNX_VERSAL_TRNG
 config XLNX_ZYNQ_DDRC
     bool
 
+config K230_IOMUX
+    bool
+
 source macio/Kconfig
diff --git a/hw/misc/k230_iomux.c b/hw/misc/k230_iomux.c
new file mode 100644
index 0000000000..cc40dc8ae4
--- /dev/null
+++ b/hw/misc/k230_iomux.c
@@ -0,0 +1,124 @@
+/*
+ * Kendryte K230 IOMUX
+ *
+ * Copyright (c) 2026 Kangjie Huang <flamboyant.h.01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Provides the Function IO configuration registers documented by the K230
+ * Technical Reference Manual.
+ *
+ * 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 "hw/misc/k230_iomux.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "trace.h"
+
+/* TRM V0.3.1 section 12.9.2.1 Function IO register list. */
+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 k230_iomux_reset(DeviceState *dev)
+{
+    K230IomuxState *s = K230_IOMUX(dev);
+
+    memcpy(s->regs, k230_iomux_reset_values,
+           sizeof(k230_iomux_reset_values));
+}
+
+static uint64_t k230_iomux_read(void *opaque, hwaddr offset, unsigned size)
+{
+    K230IomuxState *s = K230_IOMUX(opaque);
+    uint32_t value = 0;
+
+    if (offset < K230_IOMUX_REGS_SIZE) {
+        value = s->regs[offset >> 2];
+    }
+
+    trace_k230_iomux_read(offset, value);
+    return value;
+}
+
+static void k230_iomux_write(void *opaque, hwaddr offset,
+                             uint64_t value, unsigned size)
+{
+    K230IomuxState *s = K230_IOMUX(opaque);
+
+    trace_k230_iomux_write(offset, value);
+    if (offset < K230_IOMUX_REGS_SIZE) {
+        s->regs[offset >> 2] = value & K230_IOMUX_WRITABLE_MASK;
+    }
+}
+
+static const MemoryRegionOps k230_iomux_ops = {
+    .read = k230_iomux_read,
+    .write = k230_iomux_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+};
+
+static void k230_iomux_init(Object *obj)
+{
+    K230IomuxState *s = K230_IOMUX(obj);
+
+    memory_region_init_io(&s->mmio, obj, &k230_iomux_ops, s,
+                          TYPE_K230_IOMUX, K230_IOMUX_MMIO_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static const VMStateDescription vmstate_k230_iomux = {
+    .name = "k230.iomux",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, K230IomuxState, K230_IOMUX_NUM_REGS),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void k230_iomux_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->desc = "Kendryte K230 IOMUX";
+    dc->vmsd = &vmstate_k230_iomux;
+    device_class_set_legacy_reset(dc, k230_iomux_reset);
+}
+
+static const TypeInfo k230_iomux_info = {
+    .name          = TYPE_K230_IOMUX,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(K230IomuxState),
+    .instance_init = k230_iomux_init,
+    .class_init    = k230_iomux_class_init,
+};
+
+static void k230_iomux_register_types(void)
+{
+    type_register_static(&k230_iomux_info);
+}
+
+type_init(k230_iomux_register_types)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 23265f6035..31e5145a35 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -168,3 +168,5 @@ system_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
 
 # HPPA devices
 system_ss.add(when: 'CONFIG_LASI', if_true: files('lasi.c'))
+
+system_ss.add(when: 'CONFIG_K230_IOMUX', if_true: files('k230_iomux.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c9a868b3ef..388967c9e1 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -405,6 +405,10 @@ djmemc_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRI
 iosb_read(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
 iosb_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
 
+# k230_iomux.c
+k230_iomux_read(uint64_t offset, uint32_t value) "offset=0x%" PRIx64 " value=0x%" PRIx32
+k230_iomux_write(uint64_t offset, uint64_t value) "offset=0x%" PRIx64 " value=0x%" PRIx64
+
 # aspeed_sli.c
 aspeed_sli_write(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
 aspeed_sli_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
diff --git a/include/hw/misc/k230_iomux.h b/include/hw/misc/k230_iomux.h
new file mode 100644
index 0000000000..15a16ef4de
--- /dev/null
+++ b/include/hw/misc/k230_iomux.h
@@ -0,0 +1,34 @@
+/*
+ * Kendryte K230 IOMUX
+ *
+ * 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
+ *
+ * Copyright (c) 2026 Kangjie Huang <flamboyant.h.01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_K230_IOMUX_H
+#define HW_MISC_K230_IOMUX_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_K230_IOMUX "riscv.k230.iomux"
+OBJECT_DECLARE_SIMPLE_TYPE(K230IomuxState, K230_IOMUX)
+
+#define K230_IOMUX_MMIO_SIZE 0x800
+#define K230_IOMUX_NUM_REGS 64
+#define K230_IOMUX_REGS_SIZE \
+    (K230_IOMUX_NUM_REGS * sizeof(uint32_t))
+#define K230_IOMUX_WRITABLE_MASK 0x00003fff
+
+struct K230IomuxState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+    uint32_t regs[K230_IOMUX_NUM_REGS];
+};
+
+#endif /* HW_MISC_K230_IOMUX_H */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/3] hw/riscv/k230: wire up the IOMUX device
  2026-07-14 10:21 [PATCH v2 0/3] hw/riscv/k230: add IOMUX register block model Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 1/3] hw/misc/k230_iomux: add Kendryte K230 IOMUX model Kangjie Huang
@ 2026-07-14 10:22 ` Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 3/3] tests/qtest: add test for K230 IOMUX Kangjie Huang
  2 siblings, 0 replies; 4+ messages in thread
From: Kangjie Huang @ 2026-07-14 10:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Chao Liu, Alistair Francis, Palmer Dabbelt, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Pierrick Bouvier,
	Paolo Bonzini, Fabiano Rosas, Laurent Vivier, Kangjie Huang

Instantiate the K230 IOMUX device and map its MMIO region at
0x91105000, replacing the unimplemented device covering the same SoC
address window.

Select the model from the K230 machine configuration and document the
newly modeled device.

Signed-off-by: Kangjie Huang <flamboyant.h.01@gmail.com>
---
 docs/system/riscv/k230.rst |  1 +
 hw/riscv/Kconfig           |  1 +
 hw/riscv/k230.c            | 11 ++++++++---
 include/hw/riscv/k230.h    |  2 ++
 4 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/docs/system/riscv/k230.rst b/docs/system/riscv/k230.rst
index cea8202e55..b160c401fd 100644
--- a/docs/system/riscv/k230.rst
+++ b/docs/system/riscv/k230.rst
@@ -20,6 +20,7 @@ The ``k230`` machine supports the following devices:
 * Platform-Level Interrupt Controller (PLIC)
 * 2 K230 Watchdog Timer
 * 5 UART
+* K230 IOMUX register block
 
 Boot options
 ------------
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index de37c08cae..4c9fc3e7ad 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -162,3 +162,4 @@ config K230
     select SERIAL_MM
     select UNIMP
     select K230_WDT
+    select K230_IOMUX
diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
index 656f28190c..430c1646b5 100644
--- a/hw/riscv/k230.c
+++ b/hw/riscv/k230.c
@@ -110,6 +110,7 @@ static void k230_soc_init(Object *obj)
     object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY);
     object_initialize_child(obj, "k230-wdt0", &s->wdt[0], TYPE_K230_WDT);
     object_initialize_child(obj, "k230-wdt1", &s->wdt[1], TYPE_K230_WDT);
+    object_initialize_child(obj, "k230-iomux", &s->iomux, TYPE_K230_IOMUX);
 
     qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0);
     qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C908);
@@ -198,6 +199,11 @@ static void k230_soc_realize(DeviceState *dev, Error **errp)
         }
     }
 
+    /* IOMUX */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->iomux), errp)) {
+        return;
+    }
+
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[0]), 0, memmap[K230_DEV_WDT0].base);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[0]), 0,
                        qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT0_IRQ));
@@ -206,6 +212,8 @@ static void k230_soc_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[1]), 0,
                        qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT1_IRQ));
 
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->iomux), 0, memmap[K230_DEV_IOMUX].base);
+
     /* unimplemented devices */
     create_unimplemented_device("kpu.l2-cache",
                                 memmap[K230_DEV_KPU_L2_CACHE].base,
@@ -280,9 +288,6 @@ static void k230_soc_realize(DeviceState *dev, Error **errp)
     create_unimplemented_device("ipcm", memmap[K230_DEV_MAILBOX].base,
                                 memmap[K230_DEV_MAILBOX].size);
 
-    create_unimplemented_device("iomux", memmap[K230_DEV_IOMUX].base,
-                                memmap[K230_DEV_IOMUX].size);
-
     create_unimplemented_device("timer", memmap[K230_DEV_TIMER].base,
                                 memmap[K230_DEV_TIMER].size);
 
diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h
index 592e1c26bf..223e76b420 100644
--- a/include/hw/riscv/k230.h
+++ b/include/hw/riscv/k230.h
@@ -18,6 +18,7 @@
 #include "hw/core/boards.h"
 #include "hw/riscv/riscv_hart.h"
 #include "hw/watchdog/k230_wdt.h"
+#include "hw/misc/k230_iomux.h"
 
 #define C908_CPU_HARTID   (0)
 
@@ -33,6 +34,7 @@ typedef struct K230SoCState {
     RISCVHartArrayState c908_cpu; /* Small core */
 
     K230WdtState wdt[2];
+    K230IomuxState iomux;
     MemoryRegion sram;
     MemoryRegion bootrom;
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 3/3] tests/qtest: add test for K230 IOMUX
  2026-07-14 10:21 [PATCH v2 0/3] hw/riscv/k230: add IOMUX register block model Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 1/3] hw/misc/k230_iomux: add Kendryte K230 IOMUX model Kangjie Huang
  2026-07-14 10:22 ` [PATCH v2 2/3] hw/riscv/k230: wire up the IOMUX device Kangjie Huang
@ 2026-07-14 10:22 ` Kangjie Huang
  2 siblings, 0 replies; 4+ messages in thread
From: Kangjie Huang @ 2026-07-14 10:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, Chao Liu, Alistair Francis, Palmer Dabbelt, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Pierrick Bouvier,
	Paolo Bonzini, Fabiano Rosas, Laurent Vivier, Kangjie Huang

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 <flamboyant.h.01@gmail.com>
---
 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 <flamboyant.h.01@gmail.com>
+ *
+ * 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



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-14 10:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 10:21 [PATCH v2 0/3] hw/riscv/k230: add IOMUX register block model Kangjie Huang
2026-07-14 10:22 ` [PATCH v2 1/3] hw/misc/k230_iomux: add Kendryte K230 IOMUX model Kangjie Huang
2026-07-14 10:22 ` [PATCH v2 2/3] hw/riscv/k230: wire up the IOMUX device Kangjie Huang
2026-07-14 10:22 ` [PATCH v2 3/3] tests/qtest: add test for K230 IOMUX Kangjie Huang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.