On Fri, 2026-07-17 at 21:44 +0800, Chao Liu wrote:
> On Tue, Jul 14, 2026 at 06:22:00PM +0800, Kangjie Huang wrote:
> > 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 <[email protected]>
> Suggested-by: Chao Liu <[email protected]>

Are you able to review these patches as well Chao?

I feel that you know the hardware well and are probably the best person
for it

Alistair

> 
> Thanks,
> Chao
> 
> > ---
> >  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 <[email protected]>
> > + *
> > + * 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 <[email protected]>
> > + *
> > + * 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
> > 

Reply via email to