From: Wadim Mueller <wafgo01@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, "Peter Maydell" <peter.maydell@linaro.org>,
"Philippe Mathieu-Daudé" <philmd@mailo.com>,
"Bin Meng" <bmeng.cn@gmail.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Fabiano Rosas" <farosas@suse.de>,
"Wadim Mueller" <wafgo01@gmail.com>
Subject: [RFC PATCH v2 06/14] hw/misc: add TI K3 CTRL_MMR, GTC, DDRSS, SDHCI PHY and TRNG models
Date: Thu, 20 Aug 2026 14:48:06 +0200 [thread overview]
Message-ID: <20260820124824.618671-7-wafgo01@gmail.com> (raw)
In-Reply-To: <20260820124824.618671-1-wafgo01@gmail.com>
Add the small K3 support blocks the boot chain touches:
- ti-k3-ctrlmmr: control module registers, including the DEVSTAT boot
pins, which the ROM and SPL use to select the boot device.
- ti-k3-gtc: global timebase counter, read by TF-A.
- ti-k3-ddrss: DDR subsystem stub that reports a successful DRAM init
(including BIST/ECC priming status) to the R5 SPL.
- ti-k3-sdhci-phy: PHY control/calibration registers of the K3 SDHCI
wrapper, reporting calibration as done.
- ti-k3-trng: TRNG stub used by OP-TEE.
These are register-level stubs: they implement the handshakes that
firmware polls for, not the underlying hardware behaviour.
Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
hw/misc/Kconfig | 15 ++++
hw/misc/meson.build | 6 ++
hw/misc/ti-k3-ctrlmmr.c | 103 ++++++++++++++++++++++
| 98 +++++++++++++++++++++
hw/misc/ti-k3-gtc.c | 100 +++++++++++++++++++++
hw/misc/ti-k3-sdhci-phy.c | 91 +++++++++++++++++++
hw/misc/ti-k3-trng.c | 139 ++++++++++++++++++++++++++++++
hw/misc/trace-events | 4 +
include/hw/misc/ti-k3-ctrlmmr.h | 26 ++++++
| 26 ++++++
include/hw/misc/ti-k3-gtc.h | 23 +++++
include/hw/misc/ti-k3-sdhci-phy.h | 26 ++++++
include/hw/misc/ti-k3-trng.h | 35 ++++++++
13 files changed, 692 insertions(+)
create mode 100644 hw/misc/ti-k3-ctrlmmr.c
create mode 100644 hw/misc/ti-k3-ddrss.c
create mode 100644 hw/misc/ti-k3-gtc.c
create mode 100644 hw/misc/ti-k3-sdhci-phy.c
create mode 100644 hw/misc/ti-k3-trng.c
create mode 100644 include/hw/misc/ti-k3-ctrlmmr.h
create mode 100644 include/hw/misc/ti-k3-ddrss.h
create mode 100644 include/hw/misc/ti-k3-gtc.h
create mode 100644 include/hw/misc/ti-k3-sdhci-phy.h
create mode 100644 include/hw/misc/ti-k3-trng.h
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index b8860dd3e7..3e499a902d 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -143,6 +143,21 @@ config MPS2_SCC
bool
select LED
+config TI_K3_CTRLMMR
+ bool
+
+config TI_K3_GTC
+ bool
+
+config TI_K3_DDRSS
+ bool
+
+config TI_K3_SDHCI_PHY
+ bool
+
+config TI_K3_TRNG
+ bool
+
config TZ_MPC
bool
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index e86d9ad6b3..e973d7e8a4 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -96,6 +96,7 @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
'bcm2835_cprman.c',
'bcm2835_powermgt.c',
))
+
system_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
system_ss.add(when: 'CONFIG_XLNX_ZYNQ_DDRC', if_true: files('xlnx-zynq-ddrc.c'))
@@ -122,6 +123,11 @@ system_ss.add(when: 'CONFIG_STM32L4X5_RCC', if_true: files('stm32l4x5_rcc.c'))
system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
+system_ss.add(when: 'CONFIG_TI_K3_CTRLMMR', if_true: files('ti-k3-ctrlmmr.c'))
+system_ss.add(when: 'CONFIG_TI_K3_GTC', if_true: files('ti-k3-gtc.c'))
+system_ss.add(when: 'CONFIG_TI_K3_DDRSS', if_true: files('ti-k3-ddrss.c'))
+system_ss.add(when: 'CONFIG_TI_K3_SDHCI_PHY', if_true: files('ti-k3-sdhci-phy.c'))
+system_ss.add(when: 'CONFIG_TI_K3_TRNG', if_true: files('ti-k3-trng.c'))
system_ss.add(when: 'CONFIG_TZ_MPC', if_true: files('tz-mpc.c'))
system_ss.add(when: 'CONFIG_TZ_MSC', if_true: files('tz-msc.c'))
system_ss.add(when: 'CONFIG_TZ_PPC', if_true: files('tz-ppc.c'))
diff --git a/hw/misc/ti-k3-ctrlmmr.c b/hw/misc/ti-k3-ctrlmmr.c
new file mode 100644
index 0000000000..5925573075
--- /dev/null
+++ b/hw/misc/ti-k3-ctrlmmr.c
@@ -0,0 +1,103 @@
+/*
+ * TI K3 CTRL_MMR stub
+ *
+ * Minimal AM64x control MMR model: selected boot, reset-source and
+ * security-status registers are configurable; other reads return zero,
+ * writes are ignored.
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/misc/ti-k3-ctrlmmr.h"
+
+#define CTRLMMR_MAIN_DEVSTAT 0x30
+#define CTRLMMR_MCU_RST_SRC 0x18178
+/*
+ * K3_SEC_MGR_SYS_STATUS lives at offset 0x100 in the sec-ctrlmmr window.
+ * It reports the device type, e.g. GP or HS.
+ */
+#define CTRLMMR_SEC_MGR_SYS_STATUS 0x100
+#define CTRLMMR_SIZE 0x20000 /* partitions 0-7 */
+
+static uint64_t ti_k3_ctrlmmr_read(void *opaque, hwaddr addr, unsigned size)
+{
+ TIK3CtrlMmrState *s = TI_K3_CTRLMMR(opaque);
+
+ if (addr == CTRLMMR_MAIN_DEVSTAT) {
+ return s->devstat;
+ }
+ if (addr == CTRLMMR_MCU_RST_SRC) {
+ return s->rst_src;
+ }
+ if (addr == CTRLMMR_SEC_MGR_SYS_STATUS) {
+ return s->sec_mgr_sys_status;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "%s: unimplemented read @0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return 0;
+}
+
+static void ti_k3_ctrlmmr_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ /* lock-kick and pinmux writes are accepted and ignored. */
+}
+
+static const MemoryRegionOps ti_k3_ctrlmmr_ops = {
+ .read = ti_k3_ctrlmmr_read,
+ .write = ti_k3_ctrlmmr_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+};
+
+static void ti_k3_ctrlmmr_init(Object *obj)
+{
+ TIK3CtrlMmrState *s = TI_K3_CTRLMMR(obj);
+
+ memory_region_init_io(&s->iomem, obj, &ti_k3_ctrlmmr_ops, s,
+ TYPE_TI_K3_CTRLMMR, CTRLMMR_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static const Property ti_k3_ctrlmmr_properties[] = {
+ /* Default primary bootmode is eMMC (0x9 << 3). */
+ DEFINE_PROP_UINT32("devstat", TIK3CtrlMmrState, devstat, 0x48),
+ /*
+ * Report warm reset in MCU_RST_SRC. Cold/POR cause bits are not
+ * modelled by this reset-source stub.
+ */
+ DEFINE_PROP_UINT32("rst-src", TIK3CtrlMmrState, rst_src, 0x1),
+ /*
+ * Default to SYS_STATUS_DEV_TYPE_GP (0x3), matching a model without
+ * security manager and certificate authentication.
+ */
+ DEFINE_PROP_UINT32("sec-mgr-sys-status", TIK3CtrlMmrState,
+ sec_mgr_sys_status, 0x3),
+};
+
+static void ti_k3_ctrlmmr_class_init(ObjectClass *klass, const void *data)
+{
+ device_class_set_props(DEVICE_CLASS(klass), ti_k3_ctrlmmr_properties);
+}
+
+static const TypeInfo ti_k3_ctrlmmr_info = {
+ .name = TYPE_TI_K3_CTRLMMR,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TIK3CtrlMmrState),
+ .instance_init = ti_k3_ctrlmmr_init,
+ .class_init = ti_k3_ctrlmmr_class_init,
+};
+
+static void ti_k3_ctrlmmr_register_types(void)
+{
+ type_register_static(&ti_k3_ctrlmmr_info);
+}
+
+type_init(ti_k3_ctrlmmr_register_types)
--git a/hw/misc/ti-k3-ddrss.c b/hw/misc/ti-k3-ddrss.c
new file mode 100644
index 0000000000..661b88b02c
--- /dev/null
+++ b/hw/misc/ti-k3-ddrss.c
@@ -0,0 +1,98 @@
+/*
+ * TI K3 DDRSS register-file stub (AM64x, DDR4 flavour)
+ *
+ * RAM-backed DENALI CTL/PI/PHY register file. Writes are stored and read
+ * back unchanged. Init-done and optional ECC BIST_DONE status bits are ORed
+ * into reads, so the DDR bring-up handshake completes immediately.
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/misc/ti-k3-ddrss.h"
+
+/* Read-side OR masks: {offset, bits}. */
+static const struct {
+ hwaddr offset;
+ uint32_t bits;
+} ddrss_status_bits[] = {
+ { 0x214C, 1u << 0 }, /* DENALI_PI_83: PI init done */
+ { 0x0538, 1u << 13 }, /* DENALI_CTL_334: MASTER, MC_INIT grp */
+ { 0x0558, 1u << 25 }, /* DENALI_CTL_342: INT_STATUS_INIT bit1 */
+ /*
+ * ECC BIST_DONE is exposed in both places: INT_STATUS_MASTER bit 8 and
+ * INT_STATUS_BIST bit 0, resp. raw bit 16.
+ */
+ { 0x0538, 1u << 8 }, /* DENALI_CTL_334: MASTER, BIST grp */
+ { 0x0554, 1u << 16 }, /* DENALI_CTL_341: BIST fld, BIST_DONE */
+};
+
+static uint64_t ti_k3_ddrss_read(void *opaque, hwaddr addr, unsigned size)
+{
+ TIK3DdrssState *s = TI_K3_DDRSS(opaque);
+ uint32_t val = s->regs[addr >> 2];
+
+ for (size_t i = 0; i < ARRAY_SIZE(ddrss_status_bits); i++) {
+ if (addr == ddrss_status_bits[i].offset) {
+ val |= ddrss_status_bits[i].bits;
+ }
+ }
+ return val;
+}
+
+static void ti_k3_ddrss_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ TIK3DdrssState *s = TI_K3_DDRSS(opaque);
+
+ s->regs[addr >> 2] = val;
+}
+
+static const MemoryRegionOps ti_k3_ddrss_ops = {
+ .read = ti_k3_ddrss_read,
+ .write = ti_k3_ddrss_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static void ti_k3_ddrss_reset(DeviceState *dev)
+{
+ TIK3DdrssState *s = TI_K3_DDRSS(dev);
+
+ memset(s->regs, 0, sizeof(s->regs));
+}
+
+static void ti_k3_ddrss_init(Object *obj)
+{
+ TIK3DdrssState *s = TI_K3_DDRSS(obj);
+
+ memory_region_init_io(&s->iomem, obj, &ti_k3_ddrss_ops, s,
+ TYPE_TI_K3_DDRSS, TI_K3_DDRSS_CFG_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static void ti_k3_ddrss_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_legacy_reset(dc, ti_k3_ddrss_reset);
+}
+
+static const TypeInfo ti_k3_ddrss_info = {
+ .name = TYPE_TI_K3_DDRSS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TIK3DdrssState),
+ .instance_init = ti_k3_ddrss_init,
+ .class_init = ti_k3_ddrss_class_init,
+};
+
+static void ti_k3_ddrss_register_types(void)
+{
+ type_register_static(&ti_k3_ddrss_info);
+}
+
+type_init(ti_k3_ddrss_register_types)
diff --git a/hw/misc/ti-k3-gtc.c b/hw/misc/ti-k3-gtc.c
new file mode 100644
index 0000000000..b51baddc71
--- /dev/null
+++ b/hw/misc/ti-k3-gtc.c
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * TI K3 Global Timebase Counter (GTC) register stub.
+ *
+ * The GTC distributes a system counter and its nominal frequency to the ARM
+ * generic timers. Only CNTCR and CNTFID0 are implemented; the counter itself
+ * is not modelled. Reset reports an enabled 200 MHz counter, the AM64x
+ * default.
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/misc/ti-k3-gtc.h"
+
+#define TI_K3_GTC_SIZE 0x1000
+
+#define GTC_CNTCR 0x000 /* control; bit0 = EN */
+#define GTC_CNTFID0 0x020 /* frequency id 0 (Hz) */
+
+static uint64_t ti_k3_gtc_read(void *opaque, hwaddr addr, unsigned size)
+{
+ TIK3GtcState *s = TI_K3_GTC(opaque);
+
+ switch (addr) {
+ case GTC_CNTCR:
+ return s->cntcr;
+ case GTC_CNTFID0:
+ return s->cntfid0;
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: unimplemented read @0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return 0;
+ }
+}
+
+static void ti_k3_gtc_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ TIK3GtcState *s = TI_K3_GTC(opaque);
+
+ switch (addr) {
+ case GTC_CNTCR:
+ s->cntcr = (uint32_t)val;
+ break;
+ case GTC_CNTFID0:
+ s->cntfid0 = (uint32_t)val;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: unimplemented write @0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ break;
+ }
+}
+
+static const MemoryRegionOps ti_k3_gtc_ops = {
+ .read = ti_k3_gtc_read,
+ .write = ti_k3_gtc_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+};
+
+static void ti_k3_gtc_init(Object *obj)
+{
+ TIK3GtcState *s = TI_K3_GTC(obj);
+
+ memory_region_init_io(&s->iomem, obj, &ti_k3_gtc_ops, s,
+ TYPE_TI_K3_GTC, TI_K3_GTC_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static const Property ti_k3_gtc_properties[] = {
+ DEFINE_PROP_UINT32("cntcr", TIK3GtcState, cntcr, 0x1),
+ DEFINE_PROP_UINT32("cntfid0", TIK3GtcState, cntfid0, 200000000),
+};
+
+static void ti_k3_gtc_class_init(ObjectClass *klass, const void *data)
+{
+ device_class_set_props(DEVICE_CLASS(klass), ti_k3_gtc_properties);
+}
+
+static const TypeInfo ti_k3_gtc_info = {
+ .name = TYPE_TI_K3_GTC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TIK3GtcState),
+ .instance_init = ti_k3_gtc_init,
+ .class_init = ti_k3_gtc_class_init,
+};
+
+static void ti_k3_gtc_register_types(void)
+{
+ type_register_static(&ti_k3_gtc_info);
+}
+
+type_init(ti_k3_gtc_register_types)
diff --git a/hw/misc/ti-k3-sdhci-phy.c b/hw/misc/ti-k3-sdhci-phy.c
new file mode 100644
index 0000000000..10b1f56032
--- /dev/null
+++ b/hw/misc/ti-k3-sdhci-phy.c
@@ -0,0 +1,91 @@
+/*
+ * TI K3 SDHCI PHY register-file stub (AM64x)
+ *
+ * RAM-backed SDHCI companion PHY window. Drive and delay registers are stored
+ * as written. PHY_STAT1 reports CALDONE (bit 1) and DLLRDY (bit 0) set, so
+ * calibration resp. DLL lock complete immediately.
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/misc/ti-k3-sdhci-phy.h"
+
+/* Read-side OR masks: {offset, bits}. */
+static const struct {
+ hwaddr offset;
+ uint32_t bits;
+} sdhci_phy_status_bits[] = {
+ /* PHY_STAT1: CALDONE (bit 1) | DLLRDY (bit 0) */
+ { 0x130, 0x3 },
+};
+
+static uint64_t ti_k3_sdhci_phy_read(void *opaque, hwaddr addr, unsigned size)
+{
+ TIK3SdhciPhyState *s = TI_K3_SDHCI_PHY(opaque);
+ uint32_t val = s->regs[addr >> 2];
+
+ for (size_t i = 0; i < ARRAY_SIZE(sdhci_phy_status_bits); i++) {
+ if (addr == sdhci_phy_status_bits[i].offset) {
+ val |= sdhci_phy_status_bits[i].bits;
+ }
+ }
+ return val;
+}
+
+static void ti_k3_sdhci_phy_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ TIK3SdhciPhyState *s = TI_K3_SDHCI_PHY(opaque);
+
+ s->regs[addr >> 2] = val;
+}
+
+static const MemoryRegionOps ti_k3_sdhci_phy_ops = {
+ .read = ti_k3_sdhci_phy_read,
+ .write = ti_k3_sdhci_phy_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static void ti_k3_sdhci_phy_reset(DeviceState *dev)
+{
+ TIK3SdhciPhyState *s = TI_K3_SDHCI_PHY(dev);
+
+ memset(s->regs, 0, sizeof(s->regs));
+}
+
+static void ti_k3_sdhci_phy_init(Object *obj)
+{
+ TIK3SdhciPhyState *s = TI_K3_SDHCI_PHY(obj);
+
+ memory_region_init_io(&s->iomem, obj, &ti_k3_sdhci_phy_ops, s,
+ TYPE_TI_K3_SDHCI_PHY, TI_K3_SDHCI_PHY_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static void ti_k3_sdhci_phy_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_legacy_reset(dc, ti_k3_sdhci_phy_reset);
+}
+
+static const TypeInfo ti_k3_sdhci_phy_info = {
+ .name = TYPE_TI_K3_SDHCI_PHY,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TIK3SdhciPhyState),
+ .instance_init = ti_k3_sdhci_phy_init,
+ .class_init = ti_k3_sdhci_phy_class_init,
+};
+
+static void ti_k3_sdhci_phy_register_types(void)
+{
+ type_register_static(&ti_k3_sdhci_phy_info);
+}
+
+type_init(ti_k3_sdhci_phy_register_types)
diff --git a/hw/misc/ti-k3-trng.c b/hw/misc/ti-k3-trng.c
new file mode 100644
index 0000000000..14fb2d077c
--- /dev/null
+++ b/hw/misc/ti-k3-trng.c
@@ -0,0 +1,139 @@
+/*
+ * TI K3 SA2UL TRNG (EIP-76) stub (AM64x)
+ *
+ * Minimal EIP-76 register subset. STATUS reports RNG_READY, INTACK writes
+ * are accepted, OUTPUT_0..3 return two cached 64-bit pairs, and configuration
+ * registers are RAM-backed.
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/misc/ti-k3-trng.h"
+#include "trace.h"
+
+#define RNG_OUTPUT_0 0x00
+#define RNG_OUTPUT_1 0x04
+#define RNG_OUTPUT_2 0x08
+#define RNG_OUTPUT_3 0x0C
+#define RNG_STATUS 0x10
+#define RNG_READY (1u << 0)
+#define RNG_CONTROL 0x14
+
+/* Nonzero xorshift64 state reaches never zero. */
+static uint64_t ti_k3_trng_next(TIK3TrngState *s)
+{
+ s->rng_state ^= s->rng_state << 13;
+ s->rng_state ^= s->rng_state >> 7;
+ s->rng_state ^= s->rng_state << 17;
+ return s->rng_state;
+}
+
+static uint64_t ti_k3_trng_read(void *opaque, hwaddr addr, unsigned size)
+{
+ TIK3TrngState *s = TI_K3_TRNG(opaque);
+ uint32_t val;
+
+ switch (addr) {
+ case RNG_OUTPUT_0:
+ s->pair_a = ti_k3_trng_next(s);
+ val = (uint32_t)s->pair_a;
+ break;
+ case RNG_OUTPUT_1:
+ val = (uint32_t)(s->pair_a >> 32);
+ break;
+ case RNG_OUTPUT_2:
+ s->pair_b = ti_k3_trng_next(s);
+ val = (uint32_t)s->pair_b;
+ break;
+ case RNG_OUTPUT_3:
+ val = (uint32_t)(s->pair_b >> 32);
+ break;
+ case RNG_STATUS:
+ /* Always ready, never in shutdown. */
+ val = RNG_READY;
+ break;
+ default:
+ val = s->regs[addr >> 2];
+ break;
+ }
+
+ trace_ti_k3_trng_read(addr, val);
+ return val;
+}
+
+static void ti_k3_trng_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
+{
+ TIK3TrngState *s = TI_K3_TRNG(opaque);
+
+ trace_ti_k3_trng_write(addr, value);
+
+ switch (addr) {
+ case RNG_OUTPUT_0:
+ case RNG_OUTPUT_1:
+ case RNG_OUTPUT_2:
+ case RNG_OUTPUT_3:
+ /* Output registers are read-only; use RAZ/WI. */
+ break;
+ case RNG_STATUS:
+ /* STATUS is synthesized on each read, so INTACK has no state. */
+ break;
+ default:
+ s->regs[addr >> 2] = (uint32_t)value;
+ break;
+ }
+}
+
+static const MemoryRegionOps ti_k3_trng_ops = {
+ .read = ti_k3_trng_read,
+ .write = ti_k3_trng_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void ti_k3_trng_reset(DeviceState *dev)
+{
+ TIK3TrngState *s = TI_K3_TRNG(dev);
+
+ memset(s->regs, 0, sizeof(s->regs));
+ s->rng_state = 0x9e3779b97f4a7c15ULL;
+ s->pair_a = 0;
+ s->pair_b = 0;
+}
+
+static void ti_k3_trng_init(Object *obj)
+{
+ TIK3TrngState *s = TI_K3_TRNG(obj);
+
+ memory_region_init_io(&s->iomem, obj, &ti_k3_trng_ops, s,
+ TYPE_TI_K3_TRNG, TI_K3_TRNG_REGS_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static void ti_k3_trng_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_legacy_reset(dc, ti_k3_trng_reset);
+}
+
+static const TypeInfo ti_k3_trng_info = {
+ .name = TYPE_TI_K3_TRNG,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TIK3TrngState),
+ .instance_init = ti_k3_trng_init,
+ .class_init = ti_k3_trng_class_init,
+};
+
+static void ti_k3_trng_register_types(void)
+{
+ type_register_static(&ti_k3_trng_info);
+}
+
+type_init(ti_k3_trng_register_types)
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c9a868b3ef..b32ce80ea9 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -442,3 +442,7 @@ iommu_testdev_dma_read(uint64_t gva, uint32_t len) "gva=0x%" PRIx64 " len=%u"
iommu_testdev_dma_verify(uint32_t expected, uint32_t actual) "expected=0x%x actual=0x%x"
iommu_testdev_dma_result(uint32_t result) "DMA completed result=0x%x"
iommu_testdev_dma_armed(bool armed) "armed=%d"
+
+# ti-k3-trng.c
+ti_k3_trng_read(uint64_t addr, uint32_t val) "offset 0x%" PRIx64 " -> 0x%08x"
+ti_k3_trng_write(uint64_t addr, uint64_t val) "offset 0x%" PRIx64 " <- 0x%" PRIx64
diff --git a/include/hw/misc/ti-k3-ctrlmmr.h b/include/hw/misc/ti-k3-ctrlmmr.h
new file mode 100644
index 0000000000..01fb71bc74
--- /dev/null
+++ b/include/hw/misc/ti-k3-ctrlmmr.h
@@ -0,0 +1,26 @@
+/*
+ * TI K3 CTRL_MMR stub
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_MISC_TI_K3_CTRLMMR_H
+#define HW_MISC_TI_K3_CTRLMMR_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TI_K3_CTRLMMR "ti-k3-ctrlmmr"
+OBJECT_DECLARE_SIMPLE_TYPE(TIK3CtrlMmrState, TI_K3_CTRLMMR)
+
+struct TIK3CtrlMmrState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ uint32_t devstat;
+ uint32_t rst_src;
+ uint32_t sec_mgr_sys_status;
+};
+
+#endif
--git a/include/hw/misc/ti-k3-ddrss.h b/include/hw/misc/ti-k3-ddrss.h
new file mode 100644
index 0000000000..ed0f54e5c4
--- /dev/null
+++ b/include/hw/misc/ti-k3-ddrss.h
@@ -0,0 +1,26 @@
+/*
+ * TI K3 DDRSS register-file stub (AM64x)
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_MISC_TI_K3_DDRSS_H
+#define HW_MISC_TI_K3_DDRSS_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TI_K3_DDRSS "ti-k3-ddrss"
+OBJECT_DECLARE_SIMPLE_TYPE(TIK3DdrssState, TI_K3_DDRSS)
+
+#define TI_K3_DDRSS_CFG_SIZE 0x8000
+
+struct TIK3DdrssState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ uint32_t regs[TI_K3_DDRSS_CFG_SIZE / 4];
+};
+
+#endif
diff --git a/include/hw/misc/ti-k3-gtc.h b/include/hw/misc/ti-k3-gtc.h
new file mode 100644
index 0000000000..a2a22afbf6
--- /dev/null
+++ b/include/hw/misc/ti-k3-gtc.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ */
+#ifndef HW_MISC_TI_K3_GTC_H
+#define HW_MISC_TI_K3_GTC_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TI_K3_GTC "ti-k3-gtc"
+OBJECT_DECLARE_SIMPLE_TYPE(TIK3GtcState, TI_K3_GTC)
+
+struct TIK3GtcState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+
+ uint32_t cntcr; /* GTC control: bit0 EN. Read back enabled. */
+ uint32_t cntfid0; /* GTC frequency id 0, in Hz. */
+};
+
+#endif /* HW_MISC_TI_K3_GTC_H */
diff --git a/include/hw/misc/ti-k3-sdhci-phy.h b/include/hw/misc/ti-k3-sdhci-phy.h
new file mode 100644
index 0000000000..2a7296fc6f
--- /dev/null
+++ b/include/hw/misc/ti-k3-sdhci-phy.h
@@ -0,0 +1,26 @@
+/*
+ * TI K3 SDHCI PHY register-file stub (AM64x)
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_MISC_TI_K3_SDHCI_PHY_H
+#define HW_MISC_TI_K3_SDHCI_PHY_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TI_K3_SDHCI_PHY "ti-k3-sdhci-phy"
+OBJECT_DECLARE_SIMPLE_TYPE(TIK3SdhciPhyState, TI_K3_SDHCI_PHY)
+
+#define TI_K3_SDHCI_PHY_SIZE 0x400
+
+struct TIK3SdhciPhyState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ uint32_t regs[TI_K3_SDHCI_PHY_SIZE / 4];
+};
+
+#endif
diff --git a/include/hw/misc/ti-k3-trng.h b/include/hw/misc/ti-k3-trng.h
new file mode 100644
index 0000000000..b9c33b589f
--- /dev/null
+++ b/include/hw/misc/ti-k3-trng.h
@@ -0,0 +1,35 @@
+/*
+ * TI K3 SA2UL TRNG (EIP-76) stub (AM64x)
+ *
+ * Copyright (c) 2026 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_MISC_TI_K3_TRNG_H
+#define HW_MISC_TI_K3_TRNG_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TI_K3_TRNG "ti-k3-trng"
+OBJECT_DECLARE_SIMPLE_TYPE(TIK3TrngState, TI_K3_TRNG)
+
+/* EIP-76 register window: offsets 0x00..0x7c. */
+#define TI_K3_TRNG_REGS_SIZE 0x80
+
+struct TIK3TrngState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+
+ /* Nonzero xorshift64 generator state. */
+ uint64_t rng_state;
+ /* Cached pairs for OUTPUT_0/1 and OUTPUT_2/3. */
+ uint64_t pair_a;
+ uint64_t pair_b;
+
+ /* RAM-backed registers except OUTPUT_x and STATUS. */
+ uint32_t regs[TI_K3_TRNG_REGS_SIZE / 4];
+};
+
+#endif
--
2.43.0
next prev parent reply other threads:[~2026-08-20 12:51 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 12:48 [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 01/14] hw/i2c/omap_i2c: add a dedicated CONFIG_OMAP_I2C symbol Wadim Mueller
2026-08-24 15:39 ` Alex Bennée
2026-08-20 12:48 ` [RFC PATCH v2 02/14] hw/i2c/omap_i2c: implement soft reset and NACK reporting Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 03/14] hw/sd/sdhci: complete non-interrupt ADMA descriptor chains in one pass Wadim Mueller
2026-08-24 15:53 ` Alex Bennée
2026-08-20 12:48 ` [RFC PATCH v2 04/14] hw/char: add TI AM64x UART model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 05/14] hw/timer: add TI K3 DMTimer model Wadim Mueller
2026-08-20 12:48 ` Wadim Mueller [this message]
2026-08-20 12:48 ` [RFC PATCH v2 07/14] hw/misc: add TI RAT (region address translation) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 08/14] hw/misc: add TI mailbox (IPC) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 09/14] hw/misc: add TI K3 secure proxy model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 10/14] hw/misc: add TI DMSC (TI-SCI system controller) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 11/14] hw/arm: add TI K3 combined boot image parser Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 12/14] hw/arm: add TI AM64x SoC model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 13/14] hw/arm: add the am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 14/14] tests: add AM64x unit, qtest and functional tests Wadim Mueller
2026-08-20 16:25 ` Alex Bennée
2026-08-22 21:04 ` Wadim Mueller
2026-08-24 15:39 ` Alex Bennée
2026-08-21 10:26 ` [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Alex Bennée
2026-08-22 21:06 ` Wadim Mueller
2026-08-21 16:35 ` Nick Huang
2026-08-22 21:07 ` Wadim Mueller
2026-08-22 5:22 ` Bin Meng
2026-08-22 21:13 ` Wadim Mueller
2026-08-24 11:51 ` Nick Huang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260820124824.618671-7-wafgo01@gmail.com \
--to=wafgo01@gmail.com \
--cc=bmeng.cn@gmail.com \
--cc=farosas@suse.de \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@mailo.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox