All of lore.kernel.org
 help / color / mirror / Atom feed
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 ++++++++++++++++++++++
 hw/misc/ti-k3-ddrss.c             |  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 ++++++
 include/hw/misc/ti-k3-ddrss.h     |  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)
diff --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
diff --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



  parent reply	other threads:[~2026-08-20 12:51 UTC|newest]

Thread overview: 15+ 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-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-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

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 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.