From: Kyle Fox <kylefoxaustin.github@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Kyle Fox" <kylefoxaustin.github@gmail.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
qemu-arm@nongnu.org (open list:i.MX31 (kzm))
Subject: [PATCH 05/16] hw/char: add i.MX LPUART
Date: Wed, 19 Aug 2026 21:48:23 -0500 [thread overview]
Message-ID: <20260820024834.3286721-6-kylefoxaustin.github@gmail.com> (raw)
In-Reply-To: <20260820024834.3286721-1-kylefoxaustin.github@gmail.com>
The i.MX Low-Power UART. Models the register subset the Linux fsl-lpuart
driver and the SM firmware drive (BAUD/CTRL/STAT/DATA plus the TX/RX
FIFOs) as an interrupt- and poll-capable serial device. On this machine
LPUART1 is the Linux console (ttyLP0), LPUART2 the SM debug monitor and
LPUART3 the M7 console.
Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
hw/char/Kconfig | 3 +
hw/char/imx_lpuart.c | 382 +++++++++++++++++++++++++++++++++++
hw/char/meson.build | 1 +
hw/char/trace-events | 3 +
include/hw/char/imx_lpuart.h | 123 +++++++++++
5 files changed, 512 insertions(+)
create mode 100644 hw/char/imx_lpuart.c
create mode 100644 include/hw/char/imx_lpuart.h
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 020c0a84bb6..51b4c3e00ce 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -95,3 +95,6 @@ config IP_OCTAL_232
bool
default y
depends on IPACK
+
+config IMX_LPUART
+ bool
diff --git a/hw/char/imx_lpuart.c b/hw/char/imx_lpuart.c
new file mode 100644
index 00000000000..714bc3e52a4
--- /dev/null
+++ b/hw/char/imx_lpuart.c
@@ -0,0 +1,382 @@
+/*
+ * NXP i.MX LPUART (Low-Power UART) device model
+ *
+ * Copyright (c) 2026, Kyle Fox
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Modelled on hw/char/imx_serial.c for structural conventions but with
+ * the LPUART register set and semantics. TX bytes are pushed through the
+ * chardev backend synchronously; RX bytes are buffered one-deep and
+ * surface in DATA, with an interrupt raised when CTRL.RIE is set.
+ * FIFO depth is reported as 1; no DMA, no baud-rate timing, no flow
+ * control are modelled.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/char/imx_lpuart.h"
+#include "hw/core/irq.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/core/qdev-properties-system.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static void imx_lpuart_update_irq(IMXLPUARTState *s);
+
+static int imx_lpuart_post_load(void *opaque, int version_id)
+{
+ /* Recompute the IRQ line level from the restored register state. */
+ imx_lpuart_update_irq(opaque);
+ return 0;
+}
+
+static const VMStateDescription vmstate_imx_lpuart = {
+ .name = TYPE_IMX_LPUART,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = imx_lpuart_post_load,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32(baud, IMXLPUARTState),
+ VMSTATE_UINT32(stat, IMXLPUARTState),
+ VMSTATE_UINT32(ctrl, IMXLPUARTState),
+ VMSTATE_UINT32(match, IMXLPUARTState),
+ VMSTATE_UINT32(modir, IMXLPUARTState),
+ VMSTATE_UINT32(fifo, IMXLPUARTState),
+ VMSTATE_UINT32(water, IMXLPUARTState),
+ VMSTATE_UINT32(pincfg, IMXLPUARTState),
+ VMSTATE_UINT8(rx_byte, IMXLPUARTState),
+ VMSTATE_BOOL(rx_full, IMXLPUARTState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+/* Recompute the IRQ line from STAT & CTRL interrupt-enable bits. */
+static void imx_lpuart_update_irq(IMXLPUARTState *s)
+{
+ bool level =
+ ((s->stat & LPUART_STAT_RDRF) && (s->ctrl & LPUART_CTRL_RIE)) ||
+ ((s->stat & LPUART_STAT_TDRE) && (s->ctrl & LPUART_CTRL_TIE)) ||
+ ((s->stat & LPUART_STAT_TC) && (s->ctrl & LPUART_CTRL_TCIE)) ||
+ ((s->stat & LPUART_STAT_IDLE) && (s->ctrl & LPUART_CTRL_ILIE));
+
+ qemu_set_irq(s->irq, level);
+}
+
+static void imx_lpuart_reset(IMXLPUARTState *s)
+{
+ /*
+ * Power-on reset values per the i.MX LPUART chapter. STAT comes up
+ * with TDRE and TC set because the FIFO is empty.
+ */
+ s->baud = 0x0F000004; /* default OSR = 4 + SBR field */
+ s->stat = LPUART_STAT_TDRE | LPUART_STAT_TC;
+ s->ctrl = 0;
+ s->match = 0;
+ s->modir = 0;
+ s->fifo = 0;
+ s->water = 0;
+ s->pincfg = 0;
+ s->rx_byte = 0;
+ s->rx_full = false;
+}
+
+static void imx_lpuart_reset_at_boot_hold(Object *obj, ResetType type)
+{
+ IMXLPUARTState *s = IMX_LPUART(obj);
+
+ imx_lpuart_reset(s);
+ imx_lpuart_update_irq(s);
+}
+
+static uint64_t imx_lpuart_read(void *opaque, hwaddr offset, unsigned size)
+{
+ IMXLPUARTState *s = opaque;
+ uint32_t value = 0;
+ uint32_t c;
+
+ switch (offset) {
+ case LPUART_VERID:
+ value = LPUART_VERID_VALUE;
+ break;
+
+ case LPUART_PARAM:
+ /* TXFIFO and RXFIFO size fields both zero -> depth = 1. */
+ value = 0;
+ break;
+
+ case LPUART_GLOBAL:
+ value = 0;
+ break;
+
+ case LPUART_PINCFG:
+ value = s->pincfg;
+ break;
+
+ case LPUART_BAUD:
+ value = s->baud;
+ break;
+
+ case LPUART_STAT:
+ value = s->stat;
+ break;
+
+ case LPUART_CTRL:
+ value = s->ctrl;
+ break;
+
+ case LPUART_DATA:
+ if (s->rx_full) {
+ c = s->rx_byte;
+ s->rx_full = false;
+ s->stat &= ~LPUART_STAT_RDRF;
+ value = c & LPUART_DATA_MASK;
+ imx_lpuart_update_irq(s);
+ qemu_chr_fe_accept_input(&s->chr);
+ } else {
+ value = LPUART_DATA_RXEMPT;
+ }
+ break;
+
+ case LPUART_MATCH:
+ value = s->match;
+ break;
+
+ case LPUART_MODIR:
+ value = s->modir;
+ break;
+
+ case LPUART_FIFO:
+ /*
+ * Report the FIFO control bits the guest set, plus the read-only
+ * TXEMPT/RXEMPT status computed from our 1-deep model. The status
+ * bits must be derived fresh, never returned from s->fifo: the Linux
+ * driver read-modify-writes UARTFIFO during setup, so a stored RXEMPT
+ * would stick set and make its RX drain loop (while !(FIFO & RXEMPT))
+ * believe the RX FIFO is always empty - it would never read DATA, RDRF
+ * would never clear, and the RX interrupt would storm.
+ */
+ value = s->fifo & ~(LPUART_FIFO_TXEMPT | LPUART_FIFO_RXEMPT);
+ value |= LPUART_FIFO_TXEMPT; /* we drain TX instantly */
+ if (!s->rx_full) {
+ value |= LPUART_FIFO_RXEMPT;
+ }
+ break;
+
+ case LPUART_WATER:
+ /*
+ * Reflect the current fifo state in the RX/TX count fields
+ * (bits[31:24] RXCOUNT, bits[15:8] TXCOUNT). U-Boot's
+ * _lpuart32_serial_tstc() polls (water >> 24) for incoming-
+ * char detection, so RXCOUNT must update when imx_lpuart_receive
+ * stashes a byte. We are 1-deep: 0 or 1 in either slot.
+ * Preserve the guest-written watermark bits unchanged.
+ */
+ value = (s->water & 0x00ff00ffu)
+ | ((uint32_t)(s->rx_full ? 1 : 0) << 24)
+ | 0u; /* TXCOUNT always 0 - we drain TR writes instantly */
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+
+ return value;
+}
+
+static void imx_lpuart_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ IMXLPUARTState *s = opaque;
+ uint8_t ch;
+
+ switch (offset) {
+ case LPUART_VERID:
+ case LPUART_PARAM:
+ /* Read-only registers; silently ignore writes (HW behavior). */
+ break;
+
+ case LPUART_GLOBAL:
+ if (value & LPUART_GLOBAL_RST) {
+ imx_lpuart_reset(s);
+ imx_lpuart_update_irq(s);
+ }
+ break;
+
+ case LPUART_PINCFG:
+ s->pincfg = value;
+ break;
+
+ case LPUART_BAUD:
+ /*
+ * Baud-rate timing isn't modelled, but the driver reads back what
+ * it wrote. Preserve DMA-enable and other configuration bits.
+ */
+ s->baud = value;
+ trace_imx_lpuart_baud(s->baud);
+ break;
+
+ case LPUART_STAT:
+ /*
+ * STAT bits IDLE and OR are W1C; the rest are read-only status
+ * managed by the model.
+ */
+ s->stat &= ~(value & LPUART_STAT_W1C_MASK);
+ imx_lpuart_update_irq(s);
+ break;
+
+ case LPUART_CTRL:
+ s->ctrl = value;
+ imx_lpuart_update_irq(s);
+ break;
+
+ case LPUART_DATA:
+ ch = value & LPUART_DATA_MASK;
+ /*
+ * Always push the byte through the chardev backend, even if
+ * CTRL_TE is currently 0. Real silicon would queue or drop the
+ * byte until TE is enabled; in emulation we don't model that
+ * gating because some consumers (notably the Linux earlycon
+ * path under -kernel direct boot, which assumes firmware
+ * already set TE before the kernel runs) write to DATA without
+ * first enabling TE themselves. Without this, kernel console
+ * output vanishes silently and earlycon appears broken.
+ */
+ trace_imx_lpuart_tx(ch);
+ qemu_chr_fe_write_all(&s->chr, &ch, 1);
+ /*
+ * TDRE and TC are pinned high; the byte goes out instantly. A
+ * future model would clear them for one host tick, then set TC
+ * when the line goes idle.
+ */
+ s->stat |= LPUART_STAT_TDRE | LPUART_STAT_TC;
+ imx_lpuart_update_irq(s);
+ break;
+
+ case LPUART_MATCH:
+ s->match = value;
+ break;
+
+ case LPUART_MODIR:
+ s->modir = value;
+ break;
+
+ case LPUART_FIFO:
+ /*
+ * Store only the writable configuration bits. The read-only status
+ * bits (TXEMPT/RXEMPT/TXOF/RXUF) and the self-clearing flush commands
+ * (TXFLUSH/RXFLUSH) must NOT be latched: the driver read-modify-writes
+ * UARTFIFO, so latching RXEMPT would make it stick set and break the
+ * RX drain loop (see the FIFO read).
+ */
+ s->fifo = value & ~LPUART_FIFO_RO_MASK;
+ if (value & LPUART_FIFO_RXFLUSH) {
+ s->rx_full = false;
+ s->stat &= ~LPUART_STAT_RDRF;
+ }
+ imx_lpuart_update_irq(s);
+ break;
+
+ case LPUART_WATER:
+ s->water = value;
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: bad write offset 0x%" HWADDR_PRIx
+ " value 0x%" PRIx64 "\n",
+ __func__, offset, value);
+ break;
+ }
+}
+
+static int imx_lpuart_can_receive(void *opaque)
+{
+ IMXLPUARTState *s = opaque;
+
+ return ((s->ctrl & LPUART_CTRL_RE) && !s->rx_full) ? 1 : 0;
+}
+
+static void imx_lpuart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ IMXLPUARTState *s = opaque;
+
+ if (size <= 0 || s->rx_full) {
+ return;
+ }
+
+ s->rx_byte = buf[0];
+ s->rx_full = true;
+ trace_imx_lpuart_rx(s->rx_byte);
+ s->stat |= LPUART_STAT_RDRF;
+ imx_lpuart_update_irq(s);
+}
+
+static const MemoryRegionOps imx_lpuart_ops = {
+ .read = imx_lpuart_read,
+ .write = imx_lpuart_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 imx_lpuart_realize(DeviceState *dev, Error **errp)
+{
+ IMXLPUARTState *s = IMX_LPUART(dev);
+
+ qemu_chr_fe_set_handlers(&s->chr, imx_lpuart_can_receive,
+ imx_lpuart_receive, NULL, NULL, s, NULL, true);
+}
+
+static void imx_lpuart_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ IMXLPUARTState *s = IMX_LPUART(obj);
+
+ memory_region_init_io(&s->iomem, obj, &imx_lpuart_ops, s,
+ TYPE_IMX_LPUART, IMX_LPUART_REG_SIZE);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+}
+
+static const Property imx_lpuart_properties[] = {
+ DEFINE_PROP_CHR("chardev", IMXLPUARTState, chr),
+};
+
+static void imx_lpuart_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ dc->realize = imx_lpuart_realize;
+ dc->vmsd = &vmstate_imx_lpuart;
+ rc->phases.hold = imx_lpuart_reset_at_boot_hold;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+ dc->desc = "NXP i.MX LPUART";
+ device_class_set_props(dc, imx_lpuart_properties);
+}
+
+static const TypeInfo imx_lpuart_info = {
+ .name = TYPE_IMX_LPUART,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXLPUARTState),
+ .instance_init = imx_lpuart_init,
+ .class_init = imx_lpuart_class_init,
+};
+
+static void imx_lpuart_register_types(void)
+{
+ type_register_static(&imx_lpuart_info);
+}
+
+type_init(imx_lpuart_register_types)
diff --git a/hw/char/meson.build b/hw/char/meson.build
index fc3d7ee506f..440142ae803 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -41,3 +41,4 @@ system_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_vty.c'))
+system_ss.add(when: 'CONFIG_IMX_LPUART', if_true: files('imx_lpuart.c'))
diff --git a/hw/char/trace-events b/hw/char/trace-events
index a3fcc772877..6d9b71961e5 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -141,3 +141,6 @@ stm32f2xx_usart_receive(char *id, uint8_t chr) " %s receiving '%c'"
# riscv_htif.c
htif_uart_write_to_host(uint8_t device, uint8_t cmd, uint64_t payload) "device: %u cmd: %02u payload: %016" PRIx64
htif_uart_unknown_device_command(uint8_t device, uint8_t cmd, uint64_t payload) "device: %u cmd: %02u payload: %016" PRIx64
+imx_lpuart_tx(uint8_t ch) "tx 0x%02x"
+imx_lpuart_rx(uint8_t ch) "rx 0x%02x"
+imx_lpuart_baud(uint32_t baud) "baud <- 0x%08x"
diff --git a/include/hw/char/imx_lpuart.h b/include/hw/char/imx_lpuart.h
new file mode 100644
index 00000000000..a18809c432f
--- /dev/null
+++ b/include/hw/char/imx_lpuart.h
@@ -0,0 +1,123 @@
+/*
+ * NXP i.MX LPUART (Low-Power UART) device model
+ *
+ * Copyright (c) 2026, Kyle Fox
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Models the LPUART IP found in i.MX 7ULP / 8ULP / 8QXP / 95 and other
+ * recent NXP SoCs. Register layout matches the
+ * "fsl,imx95-lpuart" / "fsl,imx8ulp-lpuart" / "fsl,imx7ulp-lpuart"
+ * compatible string in the Linux fsl_lpuart driver.
+ */
+
+#ifndef IMX_LPUART_H
+#define IMX_LPUART_H
+
+#include "hw/core/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define TYPE_IMX_LPUART "imx.lpuart"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXLPUARTState, IMX_LPUART)
+
+/* MMIO size of one LPUART instance (from the device tree). */
+#define IMX_LPUART_REG_SIZE 0x1000
+
+/*
+ * Register offsets. The first four 32-bit words (VERID/PARAM/GLOBAL/
+ * PINCFG) sit before the UART register block proper, which starts at
+ * BAUD = 0x10. The Linux driver compensates with sport->reg_off = 0x10
+ * on i.MX variants; the model exposes the absolute offsets directly.
+ */
+#define LPUART_VERID 0x00
+#define LPUART_PARAM 0x04
+#define LPUART_GLOBAL 0x08
+#define LPUART_PINCFG 0x0C
+#define LPUART_BAUD 0x10
+#define LPUART_STAT 0x14
+#define LPUART_CTRL 0x18
+#define LPUART_DATA 0x1C
+#define LPUART_MATCH 0x20
+#define LPUART_MODIR 0x24
+#define LPUART_FIFO 0x28
+#define LPUART_WATER 0x2C
+
+/* GLOBAL: write GLOBAL_RST to trigger a software reset of the IP. */
+#define LPUART_GLOBAL_RST 0x00000002
+
+/* STAT bits the model implements. */
+#define LPUART_STAT_TDRE 0x00800000 /* TX data register empty */
+#define LPUART_STAT_TC 0x00400000 /* TX complete */
+#define LPUART_STAT_RDRF 0x00200000 /* RX data register full */
+#define LPUART_STAT_IDLE 0x00100000 /* RX line idle */
+#define LPUART_STAT_OR 0x00080000 /* RX overrun */
+/* RW1C mask: writing 1 to these bits clears them. */
+#define LPUART_STAT_W1C_MASK (LPUART_STAT_IDLE | LPUART_STAT_OR)
+
+/* CTRL bits the model implements. */
+#define LPUART_CTRL_TIE 0x00800000 /* TDRE IRQ enable */
+#define LPUART_CTRL_TCIE 0x00400000 /* TC IRQ enable */
+#define LPUART_CTRL_RIE 0x00200000 /* RDRF IRQ enable */
+#define LPUART_CTRL_ILIE 0x00100000 /* IDLE IRQ enable */
+#define LPUART_CTRL_TE 0x00080000 /* Transmitter enable */
+#define LPUART_CTRL_RE 0x00040000 /* Receiver enable */
+
+/* DATA: bits [7:0] carry the actual character; upper bits are status. */
+#define LPUART_DATA_MASK 0x000000FF
+#define LPUART_DATA_RXEMPT 0x00001000 /* RX buffer was empty */
+
+/*
+ * FIFO bits. TXEMPT/RXEMPT/TXOF/RXUF are read-only (status) and must never be
+ * latched from a guest write - the Linux driver read-modify-writes UARTFIFO,
+ * so a stored RXEMPT would stick and break its RX drain loop. TXFLUSH/RXFLUSH
+ * are write-1 self-clearing commands.
+ */
+#define LPUART_FIFO_TXEMPT 0x00800000
+#define LPUART_FIFO_RXEMPT 0x00400000
+#define LPUART_FIFO_TXOF 0x00020000 /* TX overflow (W1C) */
+#define LPUART_FIFO_RXUF 0x00010000 /* RX underflow (W1C) */
+#define LPUART_FIFO_TXFLUSH 0x00008000 /* self-clearing */
+#define LPUART_FIFO_RXFLUSH 0x00004000 /* self-clearing */
+#define LPUART_FIFO_RO_MASK (LPUART_FIFO_TXEMPT | LPUART_FIFO_RXEMPT | \
+ LPUART_FIFO_TXOF | LPUART_FIFO_RXUF | \
+ LPUART_FIFO_TXFLUSH | LPUART_FIFO_RXFLUSH)
+
+/*
+ * PARAM: FIFO depth is encoded as 1 << (field + 1) when nonzero, else 1.
+ * The model implements a single-byte TX path and a 1-deep RX buffer, so
+ * both TX and RX fields read back zero (depth = 1).
+ */
+#define LPUART_PARAM_TXFIFO_SHIFT 0
+#define LPUART_PARAM_RXFIFO_SHIFT 8
+
+/*
+ * VERID: report an i.MX 95-style version. The Linux driver
+ * does not branch on this field for any of the imx*ulp variants, so the
+ * exact value is not load-bearing.
+ */
+#define LPUART_VERID_VALUE 0x04040007
+
+struct IMXLPUARTState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ CharFrontend chr;
+ qemu_irq irq;
+
+ /* Register state. Only the writable bits are tracked. */
+ uint32_t baud;
+ uint32_t stat;
+ uint32_t ctrl;
+ uint32_t match;
+ uint32_t modir;
+ uint32_t fifo;
+ uint32_t water;
+ uint32_t pincfg;
+
+ /* Single-byte RX buffer (1-deep). */
+ uint8_t rx_byte;
+ bool rx_full;
+};
+
+#endif /* IMX_LPUART_H */
--
2.34.1
next prev parent reply other threads:[~2026-08-20 2:51 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 ` Kyle Fox [this message]
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 ` [PATCH 13/16] hw/misc: add i.MX 95 DPU command-sequencer stub (headless) Kyle Fox
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-6-kylefoxaustin.github@gmail.com \
--to=kylefoxaustin.github@gmail.com \
--cc=marcandre.lureau@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--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