All of lore.kernel.org
 help / color / mirror / Atom feed
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



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

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20  2:48 [PATCH 00/16] hw/arm: add the NXP i.MX 95 EVK machine Kyle Fox
2026-08-20  2:48 ` [PATCH 01/16] hw/sd/sdhci: add i.MX uSDHC SDCLK_AUTO_GATE and NO_SDMA_BOUNDARY quirks Kyle Fox
2026-08-20 11:50   ` Bin Meng
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 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.