From: Kyle Fox <kylefoxaustin.github@gmail.com>
To: qemu-devel@nongnu.org
Cc: Kyle Fox <kylefoxaustin.github@gmail.com>,
Paolo Bonzini <pbonzini@redhat.com>,
qemu-arm@nongnu.org (open list:MCIMX95-19X19-EVK...)
Subject: [PATCH 13/16] hw/misc: add i.MX 95 DPU command-sequencer stub (headless)
Date: Wed, 19 Aug 2026 21:48:31 -0500 [thread overview]
Message-ID: <20260820024834.3286721-14-kylefoxaustin.github@gmail.com> (raw)
In-Reply-To: <20260820024834.3286721-1-kylefoxaustin.github@gmail.com>
A minimal stub for the i.MX 95 DPU (display controller) command
sequencer. This machine is headless, but Linux's dpu95 driver busy-waits
with no timeout on the sequencer status register during probe, so a
reads-as-zero stub would hang userspace bring-up. The stub reports the
sequencer idle with FIFO space so the probe completes. Real display
scanout is left to a follow-on series.
Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
hw/misc/Kconfig | 3 ++
hw/misc/imx95_dpu.c | 117 +++++++++++++++++++++++++++++++++++++++++++
hw/misc/meson.build | 1 +
hw/misc/trace-events | 1 +
4 files changed, 122 insertions(+)
create mode 100644 hw/misc/imx95_dpu.c
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index e1b8c390312..59c55cb5b83 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -290,3 +290,6 @@ config IMX95_PMIC
config IMX95_XCACHE
bool
+
+config IMX95_DPU
+ bool
diff --git a/hw/misc/imx95_dpu.c b/hw/misc/imx95_dpu.c
new file mode 100644
index 00000000000..4e09b399d85
--- /dev/null
+++ b/hw/misc/imx95_dpu.c
@@ -0,0 +1,117 @@
+/*
+ * NXP i.MX 95 DPU (Display Processing Unit) command-sequencer status stub
+ *
+ * Copyright (c) 2026, Kyle Fox
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * The DPU is not modelled: this base machine is headless, and real display
+ * scanout is a follow-on series. With the real System Manager powering the
+ * display mix, however, Linux's dpu95 driver stops deferring and probes - and
+ * its blit-engine bring-up busy-waits with NO
+ * timeout on the command sequencer status register:
+ * dpu95_cs_wait_idle() spins until CMDSEQ_STATUS.IDLE is set
+ * dpu95_cs_wait_fifo_space() spins until CMDSEQ_STATUS.FIFOSPACE >= 192
+ * A plain zero-returning stub never satisfies either, so the probe kthread
+ * hangs forever, which in turn wedges wait_for_device_probe() in
+ * kernel_init() and userspace never starts.
+ *
+ * This stub returns CMDSEQ_STATUS with IDLE set and a full FIFOSPACE so both
+ * polls pass instantly; every other register reads back zero and writes are
+ * dropped. That is enough to let the probe complete (the actual command
+ * submission / fence path runs only at runtime, which we never reach). A
+ * follow-on series that models the DPU for real (adding display scanout and
+ * Wayland output) removes this stub.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+#include "trace.h"
+
+#define TYPE_IMX95_DPU "imx95.dpu"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX95DPUState, IMX95_DPU)
+
+#define IMX95_DPU_REG_SIZE 0x400000
+
+struct IMX95DPUState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+};
+
+/* Command-sequencer status, from the dpu95 blit register map. */
+#define DPU_CMDSEQ_STATUS 0x1019c
+#define DPU_CMDSEQ_STATUS_IDLE 0x40000000u
+#define DPU_CMDSEQ_STATUS_FIFOSPACE 0x0001ffffu
+
+static uint64_t imx95_dpu_read(void *opaque, hwaddr offset, unsigned size)
+{
+ if (offset == DPU_CMDSEQ_STATUS) {
+ /*
+ * Report the sequencer idle with a full FIFO. This is deliberately
+ * NOT the reset value (0x41000080: IDLE set but FIFOSPACE = 128, below
+ * the driver's threshold of 192), because the dpu95 probe polls
+ * FIFOSPACE before the enable handshake that would raise it on real
+ * silicon. Returning a constant full FIFO is sound only because the
+ * model is probe-time-only: no actual command sequence is ever
+ * submitted. If real DPU command submission is ever modelled,
+ * FIFOSPACE must track the command FIFO occupancy instead.
+ */
+ uint32_t status = DPU_CMDSEQ_STATUS_IDLE | DPU_CMDSEQ_STATUS_FIFOSPACE;
+ trace_imx95_dpu_cmdseq_status(status);
+ return status;
+ }
+ return 0;
+}
+
+static void imx95_dpu_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+}
+
+static const MemoryRegionOps imx95_dpu_ops = {
+ .read = imx95_dpu_read,
+ .write = imx95_dpu_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void imx95_dpu_init(Object *obj)
+{
+ IMX95DPUState *s = IMX95_DPU(obj);
+
+ memory_region_init_io(&s->iomem, obj, &imx95_dpu_ops, s,
+ TYPE_IMX95_DPU, IMX95_DPU_REG_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static void imx95_dpu_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+ dc->desc = "NXP i.MX 95 DPU (status stub)";
+}
+
+static const TypeInfo imx95_dpu_info = {
+ .name = TYPE_IMX95_DPU,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX95DPUState),
+ .instance_init = imx95_dpu_init,
+ .class_init = imx95_dpu_class_init,
+};
+
+static void imx95_dpu_register_types(void)
+{
+ type_register_static(&imx95_dpu_info);
+}
+
+type_init(imx95_dpu_register_types)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d7d283a191b..9d629c8efef 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -180,3 +180,4 @@ system_ss.add(when: 'CONFIG_IMX95_GPC', if_true: files('imx95_gpc.c'))
system_ss.add(when: 'CONFIG_IMX95_SRC', if_true: files('imx95_src.c'))
system_ss.add(when: 'CONFIG_IMX95_PMIC', if_true: files('imx95_pmic.c'))
system_ss.add(when: 'CONFIG_IMX95_XCACHE', if_true: files('imx95_xcache.c'))
+system_ss.add(when: 'CONFIG_IMX95_DPU', if_true: files('imx95_dpu.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 0555b15a1f3..e921b5f290a 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -466,3 +466,4 @@ pcal6408a_reg_read(uint8_t reg, uint8_t val) "PCAL6408A reg 0x%02x -> 0x%02x"
pcal6408a_reg_write(uint8_t reg, uint8_t val) "PCAL6408A reg 0x%02x <- 0x%02x"
pf53_reg_read(uint8_t reg, uint8_t val) "PF53 reg 0x%02x -> 0x%02x"
pf53_reg_write(uint8_t reg, uint8_t val) "PF53 reg 0x%02x <- 0x%02x"
+imx95_dpu_cmdseq_status(uint32_t value) "CMDSEQ_STATUS -> 0x%08x"
--
2.34.1
next prev parent reply other threads:[~2026-08-20 2:52 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260820024834.3286721-1-kylefoxaustin.github@gmail.com>
2026-08-20 2:48 ` [PATCH 02/16] hw/arm/boot: let a board preset initrd_start Kyle Fox
2026-08-20 2:48 ` [PATCH 03/16] target/arm: opt-in align-down for a misaligned PMSAv7 MPU RBAR Kyle Fox
2026-08-20 2:48 ` [PATCH 04/16] hw/arm/armv7m: forward pmsav7-rbar-align-down to the CPU Kyle Fox
2026-08-20 2:48 ` [PATCH 05/16] hw/char: add i.MX LPUART Kyle Fox
2026-08-20 2:48 ` [PATCH 06/16] hw/i2c: add i.MX LPI2C Kyle Fox
2026-08-20 2:48 ` [PATCH 07/16] hw/misc: add i.MX Messaging Unit (MU v2) Kyle Fox
2026-08-20 2:48 ` [PATCH 08/16] hw/misc: add NXP EdgeLock Enclave (ELE) responder Kyle Fox
2026-08-20 2:48 ` [PATCH 09/16] hw/timer: add i.MX 95 system counter Kyle Fox
2026-08-20 2:48 ` [PATCH 10/16] hw/misc: add i.MX 95 watchdog Kyle Fox
2026-08-20 2:48 ` [PATCH 11/16] hw/misc: add i.MX 95 ANATOP/AONMIX/GPC/SRC power and clock blocks Kyle Fox
2026-08-20 2:48 ` [PATCH 12/16] hw/misc: add i.MX 95 PMIC (PF09/PF53/PCAL6408A) and xcache controllers Kyle Fox
2026-08-20 2:48 ` Kyle Fox [this message]
2026-08-20 2:48 ` [PATCH 14/16] hw/arm: add i.MX 95 SoC container (fsl-imx95) Kyle Fox
2026-08-20 2:48 ` [PATCH 15/16] hw/arm: add i.MX 95 19x19 EVK board Kyle Fox
2026-08-20 2:48 ` [PATCH 16/16] docs, MAINTAINERS, tests/functional: add i.MX 95 EVK Kyle Fox
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=20260820024834.3286721-14-kylefoxaustin.github@gmail.com \
--to=kylefoxaustin.github@gmail.com \
--cc=pbonzini@redhat.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