Re: [PATCH v1 1/3] hw/sd: add Kendryte K230 SDHCI controller

Bin Meng <[email protected]>
Newsgroups org.nongnu.qemu-riscv,org.nongnu.qemu-devel
Message-ID <CAEUhbmXYYzy8=Sj7cBvFGLx8ArERHqHF6wtECLp_9yz+7_dm0A@mail.gmail.com>
On Wed, Jul 29, 2026 at 7:56 PM Xin Xie <[email protected]> wrote:
>
> Add a minimal K230 SDHCI model based on the generic SDHCI model. Reuse
> the generic commands and data paths while providing the extended register
> layout and documented reset values.
>
> K230 SDHCI controller contains the standard SDHCI register block followed
> by preset, extension pointer, PHY and vendor-specific registers. This model
> implements the preset and extension pointer registers as read-only, retain
> writes to most PHY and vendor-specific registers, and keep PHY_PWRGOOD
> asserted so that the K230 SDK reset sequence can complete.
>

Please split the k230_sdhci model into 2 separate models:

- One is generic Synopsys DesignWare Mobile Storage Host Controller IP
model (hw/sd/dw_mshc.c)
- Optional Canann K230 specific wrapper glue model to the dw_mshc IP
(if the generic Synopsys DesignWare MSHC IP model, or plus some unimp
region, is good enough to make the software happy, no need to create
this one)

> The SDHCI version is set to 3 due to the absence of ADMA3 support in the
> generic model.
>
> Signed-off-by: Xin Xie <[email protected]>
> ---
>  MAINTAINERS                |   2 +
>  hw/sd/Kconfig              |   4 +
>  hw/sd/k230_sdhci.c         | 311 +++++++++++++++++++++++++++++++++++++
>  hw/sd/meson.build          |   1 +
>  include/hw/sd/k230_sdhci.h |  82 ++++++++++
>  5 files changed, 400 insertions(+)
>  create mode 100644 hw/sd/k230_sdhci.c
>  create mode 100644 include/hw/sd/k230_sdhci.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6171cc7494..06285352c4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1826,8 +1826,10 @@ S: Maintained
>  F: docs/system/riscv/k230.rst
>  F: hw/riscv/k230.c
>  F: hw/watchdog/k230_wdt.c
> +F: hw/sd/k230_sdhci.c
>  F: include/hw/riscv/k230.h
>  F: include/hw/watchdog/k230_wdt.h
> +F: include/hw/sd/k230_sdhci.h
>  F: tests/qtest/k230-wdt-test.c
>
>  RX Machines
> diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig
> index 633b9afec9..e9a5d63b4d 100644
> --- a/hw/sd/Kconfig
> +++ b/hw/sd/Kconfig
> @@ -23,3 +23,7 @@ config SDHCI_PCI
>  config CADENCE_SDHCI
>      bool
>      select SDHCI
> +
> +config K230_SDHCI
> +    bool
> +    select SDHCI
> diff --git a/hw/sd/k230_sdhci.c b/hw/sd/k230_sdhci.c
> new file mode 100644
> index 0000000000..34c972a2f7
> --- /dev/null
> +++ b/hw/sd/k230_sdhci.c
> @@ -0,0 +1,311 @@
> +/*
> + * Kendryte K230 SDHCI controller
> + *
> + * Copyright (c) 2026 Xin Xie <[email protected]>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/sd/k230_sdhci.h"
> +#include "hw/sd/sdhci-internal.h"
> +#include "migration/vmstate.h"
> +
> +/*
> + * The TRM describes an SDHCI v4.20 DWC MSHC, including the v4 block-count
> + * mode, ADMA3, and extension-area registers.  QEMU's generic controller
> + * supports up to v3 and does not implement those v4 transfer semantics.
> + */
> +#define K230_SDHCI_SPEC_VERSION 3
> +
> +/*
> + * K230's Capabilities registers describe more functionality than the generic
> + * QEMU SDHCI data path currently implements.  Do not expose the following TRM
> + * capabilities to the guest:
> + *
> + * - ASYNC_INT requires an SDIO card-interrupt input and asynchronous interrupt
> + *   signalling while the SD clock is stopped.  SDBus has no such input.
> + * - TIMER_RETUNING and RETUNING_MODE require a re-tuning timer and generation
> + *   of a re-tuning request.  The generic controller only completes an initial
> + *   command-based tuning operation; it never schedules periodic re-tuning.
> + * - ADMA3 requires the SDHCI v4.20 ADMA3 descriptor and command semantics,
> + *   whereas the generic controller implements SDMA and ADMA2 only.
> + */
> +#define K230_SDHCI_CAPABILITIES_UNSUPPORTED \
> +    (R_SDHC_CAPAB_ASYNC_INT_MASK | \
> +     R_SDHC_CAPAB_TIMER_RETUNING_MASK | \
> +     R_SDHC_CAPAB_RETUNING_MODE_MASK | \
> +     R_SDHC_CAPAB_ADMA3_MASK)

The reset value of the capability does not agree with the TRM. Please
confirm the value on the real hardware, or just use the value from the
TRM.

> +#define K230_SDHCI_CAPAREG_IMPLEMENTED \
> +    (K230_SDHCI_CAPAREG_RESET & ~K230_SDHCI_CAPABILITIES_UNSUPPORTED)
> +
> +#define K230_LO8(value)     ((value) & 0xff)
> +#define K230_HI8(value)     (((value) >> 8) & 0xff)
> +
> +static const uint8_t k230_sdhci_preset_reset[K230_SDHCI_PRESET_SIZE] = {
> +    [K230_SDHCI_PRESET_INIT - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_INIT_RESET),
> +    [K230_SDHCI_PRESET_INIT - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_INIT_RESET),
> +    [K230_SDHCI_PRESET_DEFAULT_SPEED - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_DEFAULT_SPEED_RESET),
> +    [K230_SDHCI_PRESET_DEFAULT_SPEED - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_DEFAULT_SPEED_RESET),
> +    [K230_SDHCI_PRESET_HIGH_SPEED - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_HIGH_SPEED_RESET),
> +    [K230_SDHCI_PRESET_HIGH_SPEED - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_HIGH_SPEED_RESET),
> +    [K230_SDHCI_PRESET_SDR12 - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_SDR12_RESET),
> +    [K230_SDHCI_PRESET_SDR12 - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_SDR12_RESET),
> +    [K230_SDHCI_PRESET_SDR25 - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_SDR25_RESET),
> +    [K230_SDHCI_PRESET_SDR25 - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_SDR25_RESET),
> +    [K230_SDHCI_PRESET_SDR50 - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_SDR50_RESET),
> +    [K230_SDHCI_PRESET_SDR50 - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_SDR50_RESET),
> +    [K230_SDHCI_PRESET_SDR104 - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_SDR104_RESET),
> +    [K230_SDHCI_PRESET_SDR104 - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_SDR104_RESET),
> +    [K230_SDHCI_PRESET_DDR50 - K230_SDHCI_PRESET_BASE] =
> +        K230_LO8(K230_SDHCI_PRESET_DDR50_RESET),
> +    [K230_SDHCI_PRESET_DDR50 - K230_SDHCI_PRESET_BASE + 1] =
> +        K230_HI8(K230_SDHCI_PRESET_DDR50_RESET),
> +};
> +
> +static uint64_t k230_sdhci_preset_read(void *opaque, hwaddr addr,
> +                                      unsigned int size)
> +{
> +    return ldn_le_p(&k230_sdhci_preset_reset[addr], size);
> +}
> +
> +static void k230_sdhci_preset_write(void *opaque, hwaddr addr, uint64_t value,
> +                                   unsigned int size)
> +{
> +    qemu_log_mask(LOG_GUEST_ERROR,
> +                  "K230 SDHCI: write to read-only Preset Value register "
> +                  "0x%03" HWADDR_PRIx "\n",
> +                  K230_SDHCI_PRESET_BASE + addr);
> +}
> +
> +static const MemoryRegionOps k230_sdhci_preset_ops = {
> +    .read = k230_sdhci_preset_read,
> +    .write = k230_sdhci_preset_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 1,
> +        .max_access_size = 4,
> +        .unaligned = false,
> +    },
> +};
> +
> +static const uint8_t k230_sdhci_pointer_reset[K230_SDHCI_POINTER_SIZE] = {
> +    [K230_SDHCI_P_UHS2_SETTINGS - K230_SDHCI_POINTER_BASE] =
> +        K230_LO8(K230_SDHCI_P_UHS2_SETTINGS_RESET),
> +    [K230_SDHCI_P_UHS2_SETTINGS - K230_SDHCI_POINTER_BASE + 1] =
> +        K230_HI8(K230_SDHCI_P_UHS2_SETTINGS_RESET),
> +    [K230_SDHCI_P_UHS2_HOST_CAPAB - K230_SDHCI_POINTER_BASE] =
> +        K230_LO8(K230_SDHCI_P_UHS2_HOST_CAPAB_RESET),
> +    [K230_SDHCI_P_UHS2_HOST_CAPAB - K230_SDHCI_POINTER_BASE + 1] =
> +        K230_HI8(K230_SDHCI_P_UHS2_HOST_CAPAB_RESET),
> +    [K230_SDHCI_P_UHS2_TEST - K230_SDHCI_POINTER_BASE] =
> +        K230_LO8(K230_SDHCI_P_UHS2_TEST_RESET),
> +    [K230_SDHCI_P_UHS2_TEST - K230_SDHCI_POINTER_BASE + 1] =
> +        K230_HI8(K230_SDHCI_P_UHS2_TEST_RESET),
> +    [K230_SDHCI_P_EMBEDDED_CNTRL - K230_SDHCI_POINTER_BASE] =
> +        K230_LO8(K230_SDHCI_P_EMBEDDED_CNTRL_RESET),
> +    [K230_SDHCI_P_EMBEDDED_CNTRL - K230_SDHCI_POINTER_BASE + 1] =
> +        K230_HI8(K230_SDHCI_P_EMBEDDED_CNTRL_RESET),
> +    [K230_SDHCI_P_VENDOR_AREA1 - K230_SDHCI_POINTER_BASE] =
> +        K230_LO8(K230_SDHCI_P_VENDOR_AREA1_RESET),
> +    [K230_SDHCI_P_VENDOR_AREA1 - K230_SDHCI_POINTER_BASE + 1] =
> +        K230_HI8(K230_SDHCI_P_VENDOR_AREA1_RESET),
> +    [K230_SDHCI_P_VENDOR_AREA2 - K230_SDHCI_POINTER_BASE] =
> +        K230_LO8(K230_SDHCI_P_VENDOR_AREA2_RESET),
> +    [K230_SDHCI_P_VENDOR_AREA2 - K230_SDHCI_POINTER_BASE + 1] =
> +        K230_HI8(K230_SDHCI_P_VENDOR_AREA2_RESET),
> +};
> +
> +static uint64_t k230_sdhci_pointer_read(void *opaque, hwaddr addr,
> +                                       unsigned int size)
> +{
> +    return ldn_le_p(&k230_sdhci_pointer_reset[addr], size);
> +}
> +
> +static void k230_sdhci_pointer_write(void *opaque, hwaddr addr, uint64_t value,
> +                                    unsigned int size)
> +{
> +    qemu_log_mask(LOG_GUEST_ERROR,
> +                  "K230 SDHCI: write to read-only pointer register "
> +                  "0x%03" HWADDR_PRIx "\n",
> +                  K230_SDHCI_POINTER_BASE + addr);
> +}
> +
> +static const MemoryRegionOps k230_sdhci_pointer_ops = {
> +    .read = k230_sdhci_pointer_read,
> +    .write = k230_sdhci_pointer_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 1,
> +        .max_access_size = 4,
> +        .unaligned = false,
> +    },
> +};
> +
> +/*
> + * K230 uses the standard SDHCI register set at offset zero, followed by
> + * UHS-II, DWC MSHC PHY, Embedded Control, and vendor-specific blocks. Most
> + * side effects of analogue PHY behaviors not simulated.
> + *
> + * PHY_PWRGOOD is the sole synthesized status bit.  Real hardware asserts it
> + * after PHY power and reset sequencing; the SDK driver polls it during every
> + * full controller reset.  A virtual PHY has no settling interval or failure
> + * condition, so the bit is permanently asserted and cannot be cleared by a
> + * guest write.
> + */
> +static uint64_t k230_sdhci_fallback_read(void *opaque, hwaddr addr,
> +                                        unsigned int size)
> +{
> +    K230SDHCIState *s = opaque;
> +    uint64_t value = ldn_le_p(&s->fallback_regs[addr], size);
> +
> +    if (ranges_overlap(addr, size, K230_SDHCI_PHY_CNFG,
> +                       sizeof(uint32_t)) && addr <= K230_SDHCI_PHY_CNFG) {
> +        unsigned int shift = (K230_SDHCI_PHY_CNFG - addr) * 8;
> +
> +        value |= (uint64_t)K230_SDHCI_PHY_CNFG_PWRGOOD << shift;
> +    }
> +
> +    return value;
> +}
> +
> +static void k230_sdhci_fallback_write(void *opaque, hwaddr addr,
> +                                     uint64_t value, unsigned int size)
> +{
> +    K230SDHCIState *s = opaque;
> +
> +    stn_le_p(&s->fallback_regs[addr], size, value);
> +
> +    /* PWRGOOD reflects PHY state and is not software writable. */
> +    s->fallback_regs[K230_SDHCI_PHY_CNFG] |=
> +        K230_SDHCI_PHY_CNFG_PWRGOOD;
> +}
> +
> +static const MemoryRegionOps k230_sdhci_fallback_ops = {
> +    .read = k230_sdhci_fallback_read,
> +    .write = k230_sdhci_fallback_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 1,
> +        .max_access_size = 4,
> +        .unaligned = false,
> +    },
> +};
> +
> +static void k230_sdhci_reset(DeviceState *dev)
> +{
> +    K230SDHCIState *s = K230_SDHCI(dev);
> +
> +    memset(s->fallback_regs, 0, sizeof(s->fallback_regs));
> +    s->fallback_regs[K230_SDHCI_PHY_CNFG] =
> +        K230_SDHCI_PHY_CNFG_PWRGOOD;
> +    device_cold_reset(DEVICE(&s->sdhci));
> +}
> +
> +static void k230_sdhci_realize(DeviceState *dev, Error **errp)
> +{
> +    K230SDHCIState *s = K230_SDHCI(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    SysBusDevice *sdhci_sbd = SYS_BUS_DEVICE(&s->sdhci);
> +
> +    memory_region_init(&s->container, OBJECT(s), "k230.sdhci-container",
> +                       K230_SDHCI_REG_SIZE);
> +    sysbus_init_mmio(sbd, &s->container);
> +
> +    memory_region_init_io(&s->iomem_fallback, OBJECT(s),
> +                          &k230_sdhci_fallback_ops, s,
> +                          "k230.sdhci-fallback",
> +                          K230_SDHCI_REG_SIZE);
> +    memory_region_add_subregion(&s->container, 0, &s->iomem_fallback);
> +
> +    if (!sysbus_realize(sdhci_sbd, errp)) {
> +        return;
> +    }
> +    memory_region_add_subregion_overlap(
> +        &s->container, 0, sysbus_mmio_get_region(sdhci_sbd, 0), 1);
> +
> +    memory_region_init_io(&s->iomem_preset, OBJECT(s),
> +                          &k230_sdhci_preset_ops, s,
> +                          "k230.sdhci-preset", K230_SDHCI_PRESET_SIZE);
> +    memory_region_add_subregion_overlap(&s->container,
> +                                        K230_SDHCI_PRESET_BASE,
> +                                        &s->iomem_preset, 2);
> +
> +    memory_region_init_io(&s->iomem_pointer, OBJECT(s),
> +                          &k230_sdhci_pointer_ops, s,
> +                          "k230.sdhci-pointers", K230_SDHCI_POINTER_SIZE);
> +    memory_region_add_subregion_overlap(&s->container,
> +                                        K230_SDHCI_POINTER_BASE,
> +                                        &s->iomem_pointer, 2);
> +
> +    sysbus_pass_irq(sbd, sdhci_sbd);
> +    s->bus = qdev_get_child_bus(DEVICE(sdhci_sbd), "sd-bus");
> +}
> +
> +static const VMStateDescription vmstate_k230_sdhci = {
> +    .name = TYPE_K230_SDHCI,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (const VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY(fallback_regs, K230SDHCIState,
> +                            K230_SDHCI_REG_SIZE),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +static void k230_sdhci_instance_init(Object *obj)
> +{
> +    K230SDHCIState *s = K230_SDHCI(obj);
> +
> +    object_initialize_child(obj, "generic-sdhci", &s->sdhci,
> +                            TYPE_SYSBUS_SDHCI);
> +
> +    object_property_set_uint(OBJECT(&s->sdhci), "sd-spec-version",
> +                             K230_SDHCI_SPEC_VERSION,
> +                             &error_abort);
> +    object_property_set_uint(OBJECT(&s->sdhci), "capareg",
> +                             K230_SDHCI_CAPAREG_IMPLEMENTED,
> +                             &error_abort);
> +    object_property_set_uint(OBJECT(&s->sdhci), "uhs", UHS_I, &error_abort);
> +}
> +
> +static void k230_sdhci_class_init(ObjectClass *klass, const void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->desc = "Kendryte K230 SDHCI Controller";
> +    dc->realize = k230_sdhci_realize;
> +    device_class_set_legacy_reset(dc, k230_sdhci_reset);
> +    dc->vmsd = &vmstate_k230_sdhci;
> +    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> +}
> +
> +static const TypeInfo k230_sdhci_type_info = {
> +    .name = TYPE_K230_SDHCI,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(K230SDHCIState),
> +    .instance_init = k230_sdhci_instance_init,
> +    .class_init = k230_sdhci_class_init,
> +};
> +
> +static void k230_sdhci_register_types(void)
> +{
> +    type_register_static(&k230_sdhci_type_info);
> +}
> +
> +type_init(k230_sdhci_register_types)
> diff --git a/hw/sd/meson.build b/hw/sd/meson.build
> index b43d45bc56..a109635233 100644
> --- a/hw/sd/meson.build
> +++ b/hw/sd/meson.build
> @@ -10,3 +10,4 @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c'))
>  system_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c'))
>  system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c'))
>  system_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c'))
> +system_ss.add(when: 'CONFIG_K230_SDHCI', if_true: files('k230_sdhci.c'))
> diff --git a/include/hw/sd/k230_sdhci.h b/include/hw/sd/k230_sdhci.h
> new file mode 100644
> index 0000000000..a8389f1de4
> --- /dev/null
> +++ b/include/hw/sd/k230_sdhci.h
> @@ -0,0 +1,82 @@
> +/*
> + * Kendryte K230 SDHCI controller
> + *
> + * Copyright (c) 2026 Xin Xie <[email protected]>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef HW_SD_K230_SDHCI_H
> +#define HW_SD_K230_SDHCI_H
> +
> +#include "qemu/bitops.h"
> +#include "hw/sd/sdhci.h"
> +#include "qom/object.h"
> +
> +#define TYPE_K230_SDHCI "k230.sdhci"
> +OBJECT_DECLARE_SIMPLE_TYPE(K230SDHCIState, K230_SDHCI)
> +
> +#define K230_SDHCI_REG_SIZE             0x1000
> +
> +/* K230 TRM reset values for Capabilities Registers 1 and 2. */
> +#define K230_SDHCI_CAPABILITIES1_RESET  0x256ec881ULL
> +#define K230_SDHCI_CAPABILITIES2_RESET  0x0800a177ULL
> +#define K230_SDHCI_CAPAREG_RESET \
> +    ((K230_SDHCI_CAPABILITIES2_RESET << 32) \
> +    | K230_SDHCI_CAPABILITIES1_RESET)
> +
> +/* SDHCI Preset Value registers. */
> +#define K230_SDHCI_PRESET_BASE           0x060
> +#define K230_SDHCI_PRESET_SIZE           0x010
> +#define K230_SDHCI_PRESET_INIT           0x060
> +#define K230_SDHCI_PRESET_DEFAULT_SPEED  0x062
> +#define K230_SDHCI_PRESET_HIGH_SPEED     0x064
> +#define K230_SDHCI_PRESET_SDR12          0x066
> +#define K230_SDHCI_PRESET_SDR25          0x068
> +#define K230_SDHCI_PRESET_SDR50          0x06a
> +#define K230_SDHCI_PRESET_SDR104         0x06c
> +#define K230_SDHCI_PRESET_DDR50          0x06e
> +#define K230_SDHCI_PRESET_INIT_RESET          0x00fa
> +#define K230_SDHCI_PRESET_DEFAULT_SPEED_RESET 0x0004
> +#define K230_SDHCI_PRESET_HIGH_SPEED_RESET    0x0002
> +#define K230_SDHCI_PRESET_SDR12_RESET         0x0004
> +#define K230_SDHCI_PRESET_SDR25_RESET         0x0002
> +#define K230_SDHCI_PRESET_SDR50_RESET         0x0001
> +#define K230_SDHCI_PRESET_SDR104_RESET        0x0000
> +#define K230_SDHCI_PRESET_DDR50_RESET         0x0002
> +
> +/* SDHCI v4 extension-area pointer registers. */
> +#define K230_SDHCI_POINTER_BASE         0x0e0
> +#define K230_SDHCI_POINTER_SIZE         0x00c
> +#define K230_SDHCI_P_UHS2_SETTINGS      0x0e0
> +#define K230_SDHCI_P_UHS2_HOST_CAPAB    0x0e2
> +#define K230_SDHCI_P_UHS2_TEST          0x0e4
> +#define K230_SDHCI_P_EMBEDDED_CNTRL     0x0e6
> +#define K230_SDHCI_P_VENDOR_AREA1       0x0e8
> +#define K230_SDHCI_P_VENDOR_AREA2       0x0ea
> +#define K230_SDHCI_P_UHS2_SETTINGS_RESET    0x0000
> +#define K230_SDHCI_P_UHS2_HOST_CAPAB_RESET  0x0f58
> +#define K230_SDHCI_P_UHS2_TEST_RESET        0x0f68
> +#define K230_SDHCI_P_EMBEDDED_CNTRL_RESET   0x0f6c
> +#define K230_SDHCI_P_VENDOR_AREA1_RESET     0x0500
> +#define K230_SDHCI_P_VENDOR_AREA2_RESET     0x0384
> +
> +/* DWC MSHC PHY register block. */

nits: remove the ending period.
Please fix this globally in this patch series.

> +#define K230_SDHCI_PHY_CNFG             0x300
> +#define K230_SDHCI_PHY_CNFG_RSTN        BIT(0)
> +#define K230_SDHCI_PHY_CNFG_PWRGOOD     BIT(1)
> +
> +struct K230SDHCIState {
> +    SysBusDevice parent_obj;
> +
> +    MemoryRegion container;
> +    MemoryRegion iomem_fallback;
> +    MemoryRegion iomem_preset;
> +    MemoryRegion iomem_pointer;
> +    BusState *bus;
> +    uint8_t fallback_regs[K230_SDHCI_REG_SIZE];
> +
> +    SDHCIState sdhci;
> +};
> +
> +#endif

Regards,
Bin
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.