Hi Mark,
> Subject: Re: [PATCH v4 03/20] hw/i3c: Split DesignWare I3C out of Aspeed I3C
>
> On 09/02/2026 09:16, Jamin Lin wrote:
>
> > The Aspeed I3C IP block is technically an Aspeed IP block that manages
> > 6 DW I3C controllers.
> >
> > To help reflect this better and to make it easier for other SoCs to
> > use the DW I3C model, we'll split out the DW portion from the Aspeed
> > portion.
> >
> > Signed-off-by: Joe Komlodi <[email protected]>
> > Reviewed-by: Jamin Lin <[email protected]>
> > Signed-off-by: Jamin Lin <[email protected]>
> > ---
> > include/hw/i3c/aspeed_i3c.h | 19 +---
> > include/hw/i3c/dw-i3c.h | 35 +++++++
> > hw/i3c/aspeed_i3c.c | 183 +-------------------------------
> > hw/i3c/dw-i3c.c | 204
> ++++++++++++++++++++++++++++++++++++
> > hw/arm/Kconfig | 1 +
> > hw/i3c/Kconfig | 3 +
> > hw/i3c/meson.build | 1 +
> > hw/i3c/trace-events | 6 +-
> > 8 files changed, 254 insertions(+), 198 deletions(-)
> > create mode 100644 include/hw/i3c/dw-i3c.h
> > create mode 100644 hw/i3c/dw-i3c.c
> >
> > diff --git a/include/hw/i3c/aspeed_i3c.h b/include/hw/i3c/aspeed_i3c.h
> > index 7a984e1f01..f8e13b6fab 100644
> > --- a/include/hw/i3c/aspeed_i3c.h
> > +++ b/include/hw/i3c/aspeed_i3c.h
> > @@ -10,29 +10,15 @@
> > #ifndef ASPEED_I3C_H
> > #define ASPEED_I3C_H
> >
> > +#include "hw/i3c/dw-i3c.h"
> > #include "hw/core/sysbus.h"
> >
> > #define TYPE_ASPEED_I3C "aspeed.i3c"
> > -#define TYPE_ASPEED_I3C_DEVICE "aspeed.i3c.device"
> > OBJECT_DECLARE_TYPE(AspeedI3CState, AspeedI3CClass, ASPEED_I3C)
> >
> > #define ASPEED_I3C_NR_REGS (0x70 >> 2) -#define
> > ASPEED_I3C_DEVICE_NR_REGS (0x300 >> 2)
> > #define ASPEED_I3C_NR_DEVICES 6
> >
> > -OBJECT_DECLARE_SIMPLE_TYPE(AspeedI3CDevice, ASPEED_I3C_DEVICE)
> > -typedef struct AspeedI3CDevice {
> > - /* <private> */
> > - SysBusDevice parent;
> > -
> > - /* <public> */
> > - MemoryRegion mr;
> > - qemu_irq irq;
> > -
> > - uint8_t id;
> > - uint32_t regs[ASPEED_I3C_DEVICE_NR_REGS];
> > -} AspeedI3CDevice;
> > -
> > typedef struct AspeedI3CState {
> > /* <private> */
> > SysBusDevice parent;
> > @@ -43,6 +29,7 @@ typedef struct AspeedI3CState {
> > qemu_irq irq;
> >
> > uint32_t regs[ASPEED_I3C_NR_REGS];
> > - AspeedI3CDevice devices[ASPEED_I3C_NR_DEVICES];
> > + DWI3C devices[ASPEED_I3C_NR_DEVICES];
> > + uint8_t id;
> > } AspeedI3CState;
> > #endif /* ASPEED_I3C_H */
> > diff --git a/include/hw/i3c/dw-i3c.h b/include/hw/i3c/dw-i3c.h new
> > file mode 100644 index 0000000000..4550ea45fe
> > --- /dev/null
> > +++ b/include/hw/i3c/dw-i3c.h
> > @@ -0,0 +1,35 @@
> > +/*
> > + * DesignWare I3C Controller
> > + *
> > + * Copyright (C) 2021 ASPEED Technology Inc.
> > + * Copyright (C) 2025 Google, LLC.
> > + *
> > + * SPDX-License-Identifier: GPL-2.0-or-later */
> > +
> > +#ifndef DW_I3C_H
> > +#define DW_I3C_H
> > +
> > +#include "hw/core/sysbus.h"
> > +
> > +#define TYPE_DW_I3C "dw.i3c"
> > +OBJECT_DECLARE_SIMPLE_TYPE(DWI3C, DW_I3C)
> > +
> > +#define DW_I3C_NR_REGS (0x300 >> 2)
> > +
> > +typedef struct DWI3C {
>
> The typedef can be dropped because it is generated as part of
> OBJECT_DECLARE_SIMPLE_TYPE().
>
> > + /* <private> */
>
> You can drop the private comment marker as it isn't relevant anymore.
>
> > + SysBusDevice parent;
>
> This should be parent_obj as per the style guidelines.
>
> > +
> > + /* <public> */
>
> Same for the public comment marker.
>
Thanks for the review and suggestions.
Will fix them.
Jamin
> > + MemoryRegion mr;
> > + qemu_irq irq;
> > +
> > + uint8_t id;
> > + uint32_t regs[DW_I3C_NR_REGS];
> > +} DWI3C;
> > +
> > +/* Extern for other controllers that use DesignWare I3C. */ extern
> > +const VMStateDescription vmstate_dw_i3c;
> > +
> > +#endif /* DW_I3C_H */
> > diff --git a/hw/i3c/aspeed_i3c.c b/hw/i3c/aspeed_i3c.c index
> > fff259ff66..b0844d4da2 100644
> > --- a/hw/i3c/aspeed_i3c.c
> > +++ b/hw/i3c/aspeed_i3c.c
> > @@ -2,6 +2,7 @@
> > * ASPEED I3C Controller
> > *
> > * Copyright (C) 2021 ASPEED Technology Inc.
> > + * Copyright (C) 2025 Google, LLC.
> > *
> > * This code is licensed under the GPL version 2 or later. See
> > * the COPYING file in the top-level directory.
> > @@ -43,162 +44,6 @@ REG32(I3C6_REG1, 0x64)
> > FIELD(I3C6_REG1, I2C_MODE, 0, 1)
> > FIELD(I3C6_REG1, SA_EN, 15, 1)
> >
> > -/* I3C Device Registers */
> > -REG32(DEVICE_CTRL, 0x00)
> > -REG32(DEVICE_ADDR, 0x04)
> > -REG32(HW_CAPABILITY, 0x08)
> > -REG32(COMMAND_QUEUE_PORT, 0x0c)
> > -REG32(RESPONSE_QUEUE_PORT, 0x10)
> > -REG32(RX_TX_DATA_PORT, 0x14)
> > -REG32(IBI_QUEUE_STATUS, 0x18)
> > -REG32(IBI_QUEUE_DATA, 0x18)
> > -REG32(QUEUE_THLD_CTRL, 0x1c)
> > -REG32(DATA_BUFFER_THLD_CTRL, 0x20)
> > -REG32(IBI_QUEUE_CTRL, 0x24)
> > -REG32(IBI_MR_REQ_REJECT, 0x2c)
> > -REG32(IBI_SIR_REQ_REJECT, 0x30)
> > -REG32(RESET_CTRL, 0x34)
> > -REG32(SLV_EVENT_CTRL, 0x38)
> > -REG32(INTR_STATUS, 0x3c)
> > -REG32(INTR_STATUS_EN, 0x40)
> > -REG32(INTR_SIGNAL_EN, 0x44)
> > -REG32(INTR_FORCE, 0x48)
> > -REG32(QUEUE_STATUS_LEVEL, 0x4c)
> > -REG32(DATA_BUFFER_STATUS_LEVEL, 0x50)
> > -REG32(PRESENT_STATE, 0x54)
> > -REG32(CCC_DEVICE_STATUS, 0x58)
> > -REG32(DEVICE_ADDR_TABLE_POINTER, 0x5c)
> > - FIELD(DEVICE_ADDR_TABLE_POINTER, DEPTH, 16, 16)
> > - FIELD(DEVICE_ADDR_TABLE_POINTER, ADDR, 0, 16)
> > -REG32(DEV_CHAR_TABLE_POINTER, 0x60)
> > -REG32(VENDOR_SPECIFIC_REG_POINTER, 0x6c)
> > -REG32(SLV_MIPI_PID_VALUE, 0x70)
> > -REG32(SLV_PID_VALUE, 0x74)
> > -REG32(SLV_CHAR_CTRL, 0x78)
> > -REG32(SLV_MAX_LEN, 0x7c)
> > -REG32(MAX_READ_TURNAROUND, 0x80)
> > -REG32(MAX_DATA_SPEED, 0x84)
> > -REG32(SLV_DEBUG_STATUS, 0x88)
> > -REG32(SLV_INTR_REQ, 0x8c)
> > -REG32(DEVICE_CTRL_EXTENDED, 0xb0)
> > -REG32(SCL_I3C_OD_TIMING, 0xb4)
> > -REG32(SCL_I3C_PP_TIMING, 0xb8)
> > -REG32(SCL_I2C_FM_TIMING, 0xbc)
> > -REG32(SCL_I2C_FMP_TIMING, 0xc0)
> > -REG32(SCL_EXT_LCNT_TIMING, 0xc8)
> > -REG32(SCL_EXT_TERMN_LCNT_TIMING, 0xcc)
> > -REG32(BUS_FREE_TIMING, 0xd4)
> > -REG32(BUS_IDLE_TIMING, 0xd8)
> > -REG32(I3C_VER_ID, 0xe0)
> > -REG32(I3C_VER_TYPE, 0xe4)
> > -REG32(EXTENDED_CAPABILITY, 0xe8)
> > -REG32(SLAVE_CONFIG, 0xec)
> > -
> > -static const uint32_t
> ast2600_i3c_device_resets[ASPEED_I3C_DEVICE_NR_REGS] = {
> > - [R_HW_CAPABILITY] = 0x000e00bf,
> > - [R_QUEUE_THLD_CTRL] = 0x01000101,
> > - [R_I3C_VER_ID] = 0x3130302a,
> > - [R_I3C_VER_TYPE] = 0x6c633033,
> > - [R_DEVICE_ADDR_TABLE_POINTER] = 0x00080280,
> > - [R_DEV_CHAR_TABLE_POINTER] = 0x00020200,
> > - [A_VENDOR_SPECIFIC_REG_POINTER] = 0x000000b0,
> > - [R_SLV_MAX_LEN] = 0x00ff00ff,
> > -};
> > -
> > -static uint64_t aspeed_i3c_device_read(void *opaque, hwaddr offset,
> > - unsigned size)
> > -{
> > - AspeedI3CDevice *s = ASPEED_I3C_DEVICE(opaque);
> > - uint32_t addr = offset >> 2;
> > - uint64_t value;
> > -
> > - switch (addr) {
> > - case R_COMMAND_QUEUE_PORT:
> > - value = 0;
> > - break;
> > - default:
> > - value = s->regs[addr];
> > - break;
> > - }
> > -
> > - trace_aspeed_i3c_device_read(s->id, offset, value);
> > -
> > - return value;
> > -}
> > -
> > -static void aspeed_i3c_device_write(void *opaque, hwaddr offset,
> > - uint64_t value, unsigned size)
> > -{
> > - AspeedI3CDevice *s = ASPEED_I3C_DEVICE(opaque);
> > - uint32_t addr = offset >> 2;
> > -
> > - trace_aspeed_i3c_device_write(s->id, offset, value);
> > -
> > - switch (addr) {
> > - case R_HW_CAPABILITY:
> > - case R_RESPONSE_QUEUE_PORT:
> > - case R_IBI_QUEUE_DATA:
> > - case R_QUEUE_STATUS_LEVEL:
> > - case R_PRESENT_STATE:
> > - case R_CCC_DEVICE_STATUS:
> > - case R_DEVICE_ADDR_TABLE_POINTER:
> > - case R_VENDOR_SPECIFIC_REG_POINTER:
> > - case R_SLV_CHAR_CTRL:
> > - case R_SLV_MAX_LEN:
> > - case R_MAX_READ_TURNAROUND:
> > - case R_I3C_VER_ID:
> > - case R_I3C_VER_TYPE:
> > - case R_EXTENDED_CAPABILITY:
> > - qemu_log_mask(LOG_GUEST_ERROR,
> > - "%s: write to readonly register[0x%02"
> HWADDR_PRIx
> > - "] = 0x%08" PRIx64 "\n",
> > - __func__, offset, value);
> > - break;
> > - case R_RX_TX_DATA_PORT:
> > - break;
> > - case R_RESET_CTRL:
> > - break;
> > - default:
> > - s->regs[addr] = value;
> > - break;
> > - }
> > -}
> > -
> > -static const VMStateDescription aspeed_i3c_device_vmstate = {
> > - .name = TYPE_ASPEED_I3C,
> > - .version_id = 1,
> > - .minimum_version_id = 1,
> > - .fields = (const VMStateField[]){
> > - VMSTATE_UINT32_ARRAY(regs, AspeedI3CDevice,
> ASPEED_I3C_DEVICE_NR_REGS),
> > - VMSTATE_END_OF_LIST(),
> > - }
> > -};
> > -
> > -static const MemoryRegionOps aspeed_i3c_device_ops = {
> > - .read = aspeed_i3c_device_read,
> > - .write = aspeed_i3c_device_write,
> > - .endianness = DEVICE_LITTLE_ENDIAN,
> > -};
> > -
> > -static void aspeed_i3c_device_reset(DeviceState *dev) -{
> > - AspeedI3CDevice *s = ASPEED_I3C_DEVICE(dev);
> > -
> > - memcpy(s->regs, ast2600_i3c_device_resets, sizeof(s->regs));
> > -}
> > -
> > -static void aspeed_i3c_device_realize(DeviceState *dev, Error **errp)
> > -{
> > - AspeedI3CDevice *s = ASPEED_I3C_DEVICE(dev);
> > - g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I3C_DEVICE
> ".%d",
> > - s->id);
> > -
> > - sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
> > -
> > - memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i3c_device_ops,
> > - s, name, ASPEED_I3C_DEVICE_NR_REGS <<
> 2);
> > -}
> > -
> > static uint64_t aspeed_i3c_read(void *opaque, hwaddr addr, unsigned int
> size)
> > {
> > AspeedI3CState *s = ASPEED_I3C(opaque); @@ -275,7 +120,7 @@
> > static void aspeed_i3c_instance_init(Object *obj)
> >
> > for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) {
> > object_initialize_child(obj, "device[*]", &s->devices[i],
> > - TYPE_ASPEED_I3C_DEVICE);
> > + TYPE_DW_I3C);
> > }
> > }
> >
> > @@ -323,27 +168,6 @@ static void aspeed_i3c_realize(DeviceState *dev,
> > Error **errp)
> >
> > }
> >
> > -static const Property aspeed_i3c_device_properties[] = {
> > - DEFINE_PROP_UINT8("device-id", AspeedI3CDevice, id, 0),
> > -};
> > -
> > -static void aspeed_i3c_device_class_init(ObjectClass *klass, const
> > void *data) -{
> > - DeviceClass *dc = DEVICE_CLASS(klass);
> > -
> > - dc->desc = "Aspeed I3C Device";
> > - dc->realize = aspeed_i3c_device_realize;
> > - device_class_set_legacy_reset(dc, aspeed_i3c_device_reset);
> > - device_class_set_props(dc, aspeed_i3c_device_properties);
> > -}
> > -
> > -static const TypeInfo aspeed_i3c_device_info = {
> > - .name = TYPE_ASPEED_I3C_DEVICE,
> > - .parent = TYPE_SYS_BUS_DEVICE,
> > - .instance_size = sizeof(AspeedI3CDevice),
> > - .class_init = aspeed_i3c_device_class_init,
> > -};
> > -
> > static const VMStateDescription vmstate_aspeed_i3c = {
> > .name = TYPE_ASPEED_I3C,
> > .version_id = 1,
> > @@ -351,7 +175,7 @@ static const VMStateDescription vmstate_aspeed_i3c
> = {
> > .fields = (const VMStateField[]) {
> > VMSTATE_UINT32_ARRAY(regs, AspeedI3CState,
> ASPEED_I3C_NR_REGS),
> > VMSTATE_STRUCT_ARRAY(devices, AspeedI3CState,
> ASPEED_I3C_NR_DEVICES, 1,
> > - aspeed_i3c_device_vmstate,
> AspeedI3CDevice),
> > + vmstate_dw_i3c, DWI3C),
> > VMSTATE_END_OF_LIST(),
> > }
> > };
> > @@ -376,7 +200,6 @@ static const TypeInfo aspeed_i3c_info = {
> >
> > static void aspeed_i3c_register_types(void)
> > {
> > - type_register_static(&aspeed_i3c_device_info);
> > type_register_static(&aspeed_i3c_info);
> > }
> >
> > diff --git a/hw/i3c/dw-i3c.c b/hw/i3c/dw-i3c.c new file mode 100644
> > index 0000000000..c949579ea1
> > --- /dev/null
> > +++ b/hw/i3c/dw-i3c.c
> > @@ -0,0 +1,204 @@
> > +/*
> > + * DesignWare I3C Controller
> > + *
> > + * Copyright (C) 2021 ASPEED Technology Inc.
> > + * Copyright (C) 2025 Google, LLC
> > + *
> > + * SPDX-License-Identifier: GPL-2.0-or-later */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/log.h"
> > +#include "qemu/error-report.h"
> > +#include "hw/i3c/i3c.h"
> > +#include "hw/i3c/dw-i3c.h"
> > +#include "hw/core/registerfields.h"
> > +#include "hw/core/qdev-properties.h"
> > +#include "qapi/error.h"
> > +#include "migration/vmstate.h"
> > +#include "trace.h"
> > +
> > +REG32(DEVICE_CTRL, 0x00)
> > +REG32(DEVICE_ADDR, 0x04)
> > +REG32(HW_CAPABILITY, 0x08)
> > +REG32(COMMAND_QUEUE_PORT, 0x0c)
> > +REG32(RESPONSE_QUEUE_PORT, 0x10)
> > +REG32(RX_TX_DATA_PORT, 0x14)
> > +REG32(IBI_QUEUE_STATUS, 0x18)
> > +REG32(IBI_QUEUE_DATA, 0x18)
> > +REG32(QUEUE_THLD_CTRL, 0x1c)
> > +REG32(DATA_BUFFER_THLD_CTRL, 0x20)
> > +REG32(IBI_QUEUE_CTRL, 0x24)
> > +REG32(IBI_MR_REQ_REJECT, 0x2c)
> > +REG32(IBI_SIR_REQ_REJECT, 0x30)
> > +REG32(RESET_CTRL, 0x34)
> > +REG32(SLV_EVENT_CTRL, 0x38)
> > +REG32(INTR_STATUS, 0x3c)
> > +REG32(INTR_STATUS_EN, 0x40)
> > +REG32(INTR_SIGNAL_EN, 0x44)
> > +REG32(INTR_FORCE, 0x48)
> > +REG32(QUEUE_STATUS_LEVEL, 0x4c)
> > +REG32(DATA_BUFFER_STATUS_LEVEL, 0x50)
> > +REG32(PRESENT_STATE, 0x54)
> > +REG32(CCC_DEVICE_STATUS, 0x58)
> > +REG32(DEVICE_ADDR_TABLE_POINTER, 0x5c)
> > + FIELD(DEVICE_ADDR_TABLE_POINTER, DEPTH, 16, 16)
> > + FIELD(DEVICE_ADDR_TABLE_POINTER, ADDR, 0, 16)
> > +REG32(DEV_CHAR_TABLE_POINTER, 0x60)
> > +REG32(VENDOR_SPECIFIC_REG_POINTER, 0x6c)
> > +REG32(SLV_MIPI_PID_VALUE, 0x70)
> > +REG32(SLV_PID_VALUE, 0x74)
> > +REG32(SLV_CHAR_CTRL, 0x78)
> > +REG32(SLV_MAX_LEN, 0x7c)
> > +REG32(MAX_READ_TURNAROUND, 0x80)
> > +REG32(MAX_DATA_SPEED, 0x84)
> > +REG32(SLV_DEBUG_STATUS, 0x88)
> > +REG32(SLV_INTR_REQ, 0x8c)
> > +REG32(DEVICE_CTRL_EXTENDED, 0xb0)
> > +REG32(SCL_I3C_OD_TIMING, 0xb4)
> > +REG32(SCL_I3C_PP_TIMING, 0xb8)
> > +REG32(SCL_I2C_FM_TIMING, 0xbc)
> > +REG32(SCL_I2C_FMP_TIMING, 0xc0)
> > +REG32(SCL_EXT_LCNT_TIMING, 0xc8)
> > +REG32(SCL_EXT_TERMN_LCNT_TIMING, 0xcc)
> > +REG32(BUS_FREE_TIMING, 0xd4)
> > +REG32(BUS_IDLE_TIMING, 0xd8)
> > +REG32(I3C_VER_ID, 0xe0)
> > +REG32(I3C_VER_TYPE, 0xe4)
> > +REG32(EXTENDED_CAPABILITY, 0xe8)
> > +REG32(SLAVE_CONFIG, 0xec)
> > +
> > +static const uint32_t dw_i3c_resets[DW_I3C_NR_REGS] = {
> > + [R_HW_CAPABILITY] = 0x000e00bf,
> > + [R_QUEUE_THLD_CTRL] = 0x01000101,
> > + [R_I3C_VER_ID] = 0x3130302a,
> > + [R_I3C_VER_TYPE] = 0x6c633033,
> > + [R_DEVICE_ADDR_TABLE_POINTER] = 0x00080280,
> > + [R_DEV_CHAR_TABLE_POINTER] = 0x00020200,
> > + [A_VENDOR_SPECIFIC_REG_POINTER] = 0x000000b0,
> > + [R_SLV_MAX_LEN] = 0x00ff00ff,
> > +};
> > +
> > +static uint64_t dw_i3c_read(void *opaque, hwaddr offset, unsigned
> > +size) {
> > + DWI3C *s = DW_I3C(opaque);
> > + uint32_t addr = offset >> 2;
> > + uint64_t value;
> > +
> > + switch (addr) {
> > + case R_COMMAND_QUEUE_PORT:
> > + value = 0;
> > + break;
> > + default:
> > + value = s->regs[addr];
> > + break;
> > + }
> > +
> > + trace_dw_i3c_read(s->id, offset, value);
> > +
> > + return value;
> > +}
> > +
> > +static void dw_i3c_write(void *opaque, hwaddr offset, uint64_t value,
> > + unsigned size) {
> > + DWI3C *s = DW_I3C(opaque);
> > + uint32_t addr = offset >> 2;
> > +
> > + trace_dw_i3c_write(s->id, offset, value);
> > +
> > + switch (addr) {
> > + case R_HW_CAPABILITY:
> > + case R_RESPONSE_QUEUE_PORT:
> > + case R_IBI_QUEUE_DATA:
> > + case R_QUEUE_STATUS_LEVEL:
> > + case R_PRESENT_STATE:
> > + case R_CCC_DEVICE_STATUS:
> > + case R_DEVICE_ADDR_TABLE_POINTER:
> > + case R_VENDOR_SPECIFIC_REG_POINTER:
> > + case R_SLV_CHAR_CTRL:
> > + case R_SLV_MAX_LEN:
> > + case R_MAX_READ_TURNAROUND:
> > + case R_I3C_VER_ID:
> > + case R_I3C_VER_TYPE:
> > + case R_EXTENDED_CAPABILITY:
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: write to readonly register[0x%02"
> HWADDR_PRIx
> > + "] = 0x%08" PRIx64 "\n",
> > + __func__, offset, value);
> > + break;
> > + case R_RX_TX_DATA_PORT:
> > + break;
> > + case R_RESET_CTRL:
> > + break;
> > + default:
> > + s->regs[addr] = value;
> > + break;
> > + }
> > +}
> > +
> > +const VMStateDescription vmstate_dw_i3c = {
> > + .name = TYPE_DW_I3C,
> > + .version_id = 1,
> > + .minimum_version_id = 1,
> > + .fields = (VMStateField[]){
> > + VMSTATE_UINT32_ARRAY(regs, DWI3C, DW_I3C_NR_REGS),
> > + VMSTATE_END_OF_LIST(),
> > + }
> > +};
> > +
> > +static const MemoryRegionOps dw_i3c_ops = {
> > + .read = dw_i3c_read,
> > + .write = dw_i3c_write,
> > + .endianness = DEVICE_LITTLE_ENDIAN, };
> > +
> > +static void dw_i3c_reset_enter(Object *obj, ResetType type) {
> > + DWI3C *s = DW_I3C(obj);
> > +
> > + memcpy(s->regs, dw_i3c_resets, sizeof(s->regs)); }
> > +
> > +static void dw_i3c_realize(DeviceState *dev, Error **errp) {
> > + DWI3C *s = DW_I3C(dev);
> > + g_autofree char *name = g_strdup_printf(TYPE_DW_I3C ".%d",
> > +s->id);
> > +
> > + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
> > +
> > + memory_region_init_io(&s->mr, OBJECT(s), &dw_i3c_ops, s, name,
> > + DW_I3C_NR_REGS << 2);
> > + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr); }
> > +
> > +static const Property dw_i3c_properties[] = {
> > + DEFINE_PROP_UINT8("device-id", DWI3C, id, 0), };
> > +
> > +static void dw_i3c_class_init(ObjectClass *klass, const void *data) {
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + ResettableClass *rc = RESETTABLE_CLASS(klass);
> > +
> > + rc->phases.enter = dw_i3c_reset_enter;
> > +
> > + dc->desc = "DesignWare I3C Controller";
> > + dc->realize = dw_i3c_realize;
> > + dc->vmsd = &vmstate_dw_i3c;
> > + device_class_set_props(dc, dw_i3c_properties); }
> > +
> > +static const TypeInfo dw_i3c_info = {
> > + .name = TYPE_DW_I3C,
> > + .parent = TYPE_SYS_BUS_DEVICE,
> > + .instance_size = sizeof(DWI3C),
> > + .class_init = dw_i3c_class_init,
> > +};
> > +
> > +static void dw_i3c_register_types(void) {
> > + type_register_static(&dw_i3c_info);
> > +}
>
> Again you probably want to use DECLARE_TYPES() here.
>
> > +type_init(dw_i3c_register_types);
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
> > 8344b9769f..d545ecd712 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -546,6 +546,7 @@ config ASPEED_SOC
> > select FTGMAC100
> > select I2C
> > select I3C
> > + select DW_I3C
> > select DPS310
> > select PCA9552
> > select PCA9554
> > diff --git a/hw/i3c/Kconfig b/hw/i3c/Kconfig index
> > e07fe445c6..ecec77d6fc 100644
> > --- a/hw/i3c/Kconfig
> > +++ b/hw/i3c/Kconfig
> > @@ -1,2 +1,5 @@
> > config I3C
> > bool
> > +
> > +config DW_I3C
> > + bool
> > diff --git a/hw/i3c/meson.build b/hw/i3c/meson.build index
> > fb127613fe..83d75e7d5c 100644
> > --- a/hw/i3c/meson.build
> > +++ b/hw/i3c/meson.build
> > @@ -1,4 +1,5 @@
> > i3c_ss = ss.source_set()
> > i3c_ss.add(when: 'CONFIG_I3C', if_true: files('core.c'))
> > i3c_ss.add(when: 'CONFIG_ASPEED_SOC', if_true:
> > files('aspeed_i3c.c'))
> > +i3c_ss.add(when: 'CONFIG_DW_I3C', if_true: files('dw-i3c.c'))
> > system_ss.add_all(when: 'CONFIG_I3C', if_true: i3c_ss) diff --git
> > a/hw/i3c/trace-events b/hw/i3c/trace-events index
> > cdf7cb07f6..2d944387db 100644
> > --- a/hw/i3c/trace-events
> > +++ b/hw/i3c/trace-events
> > @@ -3,8 +3,10 @@
> > # aspeed_i3c.c
> > aspeed_i3c_read(uint64_t offset, uint64_t data) "I3C read: offset 0x%"
> PRIx64 " data 0x%" PRIx64
> > aspeed_i3c_write(uint64_t offset, uint64_t data) "I3C write: offset
> > 0x%" PRIx64 " data 0x%" PRIx64 -aspeed_i3c_device_read(uint32_t
> > deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] read: offset
> > 0x%" PRIx64 " data 0x%" PRIx64 -aspeed_i3c_device_write(uint32_t
> > deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] write: offset
> > 0x%" PRIx64 " data 0x%" PRIx64
> > +
> > +# dw-i3c,c
> > +dw_i3c_read(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C
> > +Dev[%u] read: offset 0x%" PRIx64 " data 0x%" PRIx64
> > +dw_i3c_write(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C
> > +Dev[%u] write: offset 0x%" PRIx64 " data 0x%" PRIx64
> >
> > # core.c
> > i3c_target_event(uint8_t address, uint8_t event) "I3C target 0x%"
> > PRIx8 " event 0x%" PRIx8
>
>
>
> ATB,
>
> Mark.