QEMU-Arm Archive on 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>,
	qemu-arm@nongnu.org (open list:MCIMX95-19X19-EVK...)
Subject: [PATCH 12/16] hw/misc: add i.MX 95 PMIC (PF09/PF53/PCAL6408A) and xcache controllers
Date: Wed, 19 Aug 2026 21:48:30 -0500	[thread overview]
Message-ID: <20260820024834.3286721-13-kylefoxaustin.github@gmail.com> (raw)
In-Reply-To: <20260820024834.3286721-1-kylefoxaustin.github@gmail.com>

The i.MX 95 EVK power devices on LPI2C - the PF09 and PF53 regulators
and the PCAL6408A IO expander that the SM firmware sequences during
power-up - modelled as I2C-slave register files, plus the xcache (cache
controller) register block.

Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
 hw/misc/Kconfig        |   7 +
 hw/misc/imx95_pmic.c   | 357 +++++++++++++++++++++++++++++++++++++++++
 hw/misc/imx95_xcache.c | 185 +++++++++++++++++++++
 hw/misc/meson.build    |   2 +
 hw/misc/trace-events   |   8 +
 5 files changed, 559 insertions(+)
 create mode 100644 hw/misc/imx95_pmic.c
 create mode 100644 hw/misc/imx95_xcache.c

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1e1cae92f6f..e1b8c390312 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -283,3 +283,10 @@ config IMX95_GPC
 
 config IMX95_SRC
     bool
+
+config IMX95_PMIC
+    bool
+    select I2C
+
+config IMX95_XCACHE
+    bool
diff --git a/hw/misc/imx95_pmic.c b/hw/misc/imx95_pmic.c
new file mode 100644
index 00000000000..e7101f1ed06
--- /dev/null
+++ b/hw/misc/imx95_pmic.c
@@ -0,0 +1,357 @@
+/*
+ * Minimal I2C device models for the i.MX 95 EVK System Manager:
+ *   - PF09 (PF0900) PMIC          (TYPE_PF09_PMIC,  addr 0x08, CRC'd)
+ *   - PCAL6408A 8-bit IO expander (TYPE_PCAL6408A,  addr 0x20)
+ *   - PF53 buck regulator         (TYPE_PF53_PMIC,  addr 0x2a/0x29)
+ *
+ * Copyright (c) 2026, Kyle Fox
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * The NXP SM firmware probes/configures both over LPI2C1 during board
+ * init (BRD_SM_SerialDevicesInit); a failed transfer aborts SM init.
+ * These are register-file models: writes store, reads return the stored
+ * byte. The PF09 driver protects each transfer with a J1850 CRC, so the
+ * PF09 read path appends the CRC the driver expects
+ * (CRC_J1850((devAddr<<1)|1, reg, data)); without it PF09_Init fails.
+ * No actual PMIC/regulator or GPIO behaviour is modelled.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "hw/i2c/i2c.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+/* ---- J1850 CRC (matches imx-sm components/crc/crc.c CRC_J1850) ---- */
+#define CRC_J1850_POLY  0x1Du
+
+static uint8_t crc_j1850(const uint8_t *p, unsigned n)
+{
+    uint32_t crc = 0xffu;
+
+    for (unsigned i = 0; i < n; i++) {
+        crc ^= p[i];
+        for (unsigned b = 0; b < 8; b++) {
+            crc = (crc & 0x80u) ? ((crc << 1) ^ CRC_J1850_POLY)
+                                : ((crc << 1) & 0xffu);
+        }
+    }
+    return (uint8_t)crc;
+}
+
+/* ============================ PF09 PMIC ============================ */
+
+#define TYPE_PF09_PMIC "pf09-pmic"
+OBJECT_DECLARE_SIMPLE_TYPE(PF09State, PF09_PMIC)
+
+#define PF09_NUM_REG    256
+
+struct PF09State {
+    I2CSlave    parent_obj;
+
+    uint8_t     regs[PF09_NUM_REG];
+    uint8_t     cur_reg;
+    uint32_t    wcount;     /* bytes received since START(write) */
+    uint32_t    rcount;     /* bytes returned since START(read) */
+};
+
+static int pf09_event(I2CSlave *i2c, enum i2c_event event)
+{
+    PF09State *s = PF09_PMIC(i2c);
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->wcount = 0;
+        break;
+    case I2C_START_RECV:
+        s->rcount = 0;
+        break;
+    default:
+        break;
+    }
+    return 0;   /* ACK */
+}
+
+static int pf09_send(I2CSlave *i2c, uint8_t data)
+{
+    PF09State *s = PF09_PMIC(i2c);
+
+    if (s->wcount == 0) {
+        s->cur_reg = data;          /* register address */
+    } else if (s->wcount == 1) {
+        s->regs[s->cur_reg] = data; /* data byte */
+        trace_pf09_reg_write(s->cur_reg, data);
+    }
+    /* wcount >= 2 is the trailing CRC byte: accept and ignore. */
+    s->wcount++;
+    return 0;   /* ACK */
+}
+
+static uint8_t pf09_recv(I2CSlave *i2c)
+{
+    PF09State *s = PF09_PMIC(i2c);
+    uint8_t val;
+
+    if (s->rcount == 0) {
+        val = s->regs[s->cur_reg];
+        trace_pf09_reg_read(s->cur_reg, val);
+    } else {
+        /* CRC over (devAddr<<1)|1, reg, data - what PF09_PmicRead checks. */
+        uint8_t buf[3] = {
+            (uint8_t)((i2c->address << 1) | 1u),
+            s->cur_reg,
+            s->regs[s->cur_reg],
+        };
+        val = crc_j1850(buf, 3);
+    }
+    s->rcount++;
+    return val;
+}
+
+static void pf09_reset_hold(Object *obj, ResetType type)
+{
+    PF09State *s = PF09_PMIC(obj);
+
+    memset(s->regs, 0, sizeof(s->regs));
+    s->cur_reg = 0;
+    s->wcount = 0;
+    s->rcount = 0;
+    /* REV_ID >= 0x20 lets PF09_Init skip the STANDBY-monitor write. */
+    s->regs[0x00] = 0x20;
+}
+
+static const VMStateDescription vmstate_pf09 = {
+    .name = TYPE_PF09_PMIC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_I2C_SLAVE(parent_obj, PF09State),
+        VMSTATE_UINT8_ARRAY(regs, PF09State, PF09_NUM_REG),
+        VMSTATE_UINT8(cur_reg, PF09State),
+        VMSTATE_UINT32(wcount, PF09State),
+        VMSTATE_UINT32(rcount, PF09State),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void pf09_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->event = pf09_event;
+    k->recv = pf09_recv;
+    k->send = pf09_send;
+    dc->vmsd = &vmstate_pf09;
+    rc->phases.hold = pf09_reset_hold;
+    dc->desc = "NXP PF09 PMIC (i.MX95 SM stub)";
+}
+
+static const TypeInfo pf09_info = {
+    .name          = TYPE_PF09_PMIC,
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(PF09State),
+    .class_init    = pf09_class_init,
+};
+
+/* ========================== PCAL6408A ============================= */
+
+#define TYPE_PCAL6408A "pcal6408a"
+OBJECT_DECLARE_SIMPLE_TYPE(PCAL6408AState, PCAL6408A)
+
+#define PCAL6408A_NUM_REG   256
+
+struct PCAL6408AState {
+    I2CSlave    parent_obj;
+
+    uint8_t     regs[PCAL6408A_NUM_REG];
+    uint8_t     cur_reg;
+    uint32_t    wcount;
+};
+
+static int pcal6408a_event(I2CSlave *i2c, enum i2c_event event)
+{
+    PCAL6408AState *s = PCAL6408A(i2c);
+
+    if (event == I2C_START_SEND) {
+        s->wcount = 0;
+    }
+    return 0;
+}
+
+static int pcal6408a_send(I2CSlave *i2c, uint8_t data)
+{
+    PCAL6408AState *s = PCAL6408A(i2c);
+
+    if (s->wcount == 0) {
+        s->cur_reg = data;
+    } else {
+        trace_pcal6408a_reg_write(s->cur_reg, data);
+        s->regs[s->cur_reg++] = data;
+    }
+    s->wcount++;
+    return 0;
+}
+
+static uint8_t pcal6408a_recv(I2CSlave *i2c)
+{
+    PCAL6408AState *s = PCAL6408A(i2c);
+    uint8_t val = s->regs[s->cur_reg];
+
+    trace_pcal6408a_reg_read(s->cur_reg, val);
+    s->cur_reg++;
+    return val;
+}
+
+static void pcal6408a_reset_hold(Object *obj, ResetType type)
+{
+    PCAL6408AState *s = PCAL6408A(obj);
+
+    memset(s->regs, 0, sizeof(s->regs));
+    s->cur_reg = 0;
+    s->wcount = 0;
+}
+
+static const VMStateDescription vmstate_pcal6408a = {
+    .name = TYPE_PCAL6408A,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_I2C_SLAVE(parent_obj, PCAL6408AState),
+        VMSTATE_UINT8_ARRAY(regs, PCAL6408AState, PCAL6408A_NUM_REG),
+        VMSTATE_UINT8(cur_reg, PCAL6408AState),
+        VMSTATE_UINT32(wcount, PCAL6408AState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void pcal6408a_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->event = pcal6408a_event;
+    k->recv = pcal6408a_recv;
+    k->send = pcal6408a_send;
+    dc->vmsd = &vmstate_pcal6408a;
+    rc->phases.hold = pcal6408a_reset_hold;
+    dc->desc = "NXP PCAL6408A IO expander (i.MX95 SM stub)";
+}
+
+static const TypeInfo pcal6408a_info = {
+    .name          = TYPE_PCAL6408A,
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(PCAL6408AState),
+    .class_init    = pcal6408a_class_init,
+};
+
+/* ============================ PF53 PMIC ============================ */
+
+/*
+ * PF5301 / PF5302 (PF53-family) buck regulators on the same LPI2C bus.
+ * BRD_SM_SerialDevicesInit calls PF53_Init() on each, which only reads
+ * the DEV_ID register and checks that the transfer ACKs (it does not
+ * validate the value, and the SM configures crcEn=false for these). So a
+ * plain register file that ACKs is sufficient to get past SM init.
+ */
+#define TYPE_PF53_PMIC "pf53-pmic"
+OBJECT_DECLARE_SIMPLE_TYPE(PF53State, PF53_PMIC)
+
+#define PF53_NUM_REG    256
+
+struct PF53State {
+    I2CSlave    parent_obj;
+
+    uint8_t     regs[PF53_NUM_REG];
+    uint8_t     cur_reg;
+    uint32_t    wcount;
+};
+
+static int pf53_event(I2CSlave *i2c, enum i2c_event event)
+{
+    PF53State *s = PF53_PMIC(i2c);
+
+    if (event == I2C_START_SEND) {
+        s->wcount = 0;
+    }
+    return 0;
+}
+
+static int pf53_send(I2CSlave *i2c, uint8_t data)
+{
+    PF53State *s = PF53_PMIC(i2c);
+
+    if (s->wcount == 0) {
+        s->cur_reg = data;
+    } else {
+        trace_pf53_reg_write(s->cur_reg, data);
+        s->regs[s->cur_reg++] = data;
+    }
+    s->wcount++;
+    return 0;
+}
+
+static uint8_t pf53_recv(I2CSlave *i2c)
+{
+    PF53State *s = PF53_PMIC(i2c);
+    uint8_t val = s->regs[s->cur_reg];
+
+    trace_pf53_reg_read(s->cur_reg, val);
+    s->cur_reg++;
+    return val;
+}
+
+static void pf53_reset_hold(Object *obj, ResetType type)
+{
+    PF53State *s = PF53_PMIC(obj);
+
+    memset(s->regs, 0, sizeof(s->regs));
+    s->cur_reg = 0;
+    s->wcount = 0;
+}
+
+static const VMStateDescription vmstate_pf53 = {
+    .name = TYPE_PF53_PMIC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_I2C_SLAVE(parent_obj, PF53State),
+        VMSTATE_UINT8_ARRAY(regs, PF53State, PF53_NUM_REG),
+        VMSTATE_UINT8(cur_reg, PF53State),
+        VMSTATE_UINT32(wcount, PF53State),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void pf53_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->event = pf53_event;
+    k->recv = pf53_recv;
+    k->send = pf53_send;
+    dc->vmsd = &vmstate_pf53;
+    rc->phases.hold = pf53_reset_hold;
+    dc->desc = "NXP PF53 PMIC (i.MX95 SM stub)";
+}
+
+static const TypeInfo pf53_info = {
+    .name          = TYPE_PF53_PMIC,
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(PF53State),
+    .class_init    = pf53_class_init,
+};
+
+static void imx95_pmic_register_types(void)
+{
+    type_register_static(&pf09_info);
+    type_register_static(&pcal6408a_info);
+    type_register_static(&pf53_info);
+}
+
+type_init(imx95_pmic_register_types)
diff --git a/hw/misc/imx95_xcache.c b/hw/misc/imx95_xcache.c
new file mode 100644
index 00000000000..ef7752a6201
--- /dev/null
+++ b/hw/misc/imx95_xcache.c
@@ -0,0 +1,185 @@
+/*
+ * NXP i.MX 95 XCACHE controller stub model
+ *
+ * Copyright (c) 2026, Kyle Fox
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Minimal model of the M33 XCACHE controller (the two instances at
+ * 0x44400000 "PC" and 0x44400800 "PS"). The NXP System Manager firmware
+ * enables and invalidates its caches early in init by writing the cache
+ * control register (CCR): it sets ENCACHE plus the invalidate/push
+ * command bits and the GO bit, then polls.
+ *
+ * QEMU has no cache to model, so the only behaviour that matters is the
+ * self-clearing of the command bits: real hardware clears GO and the
+ * INVWn/PUSHWn bits once the (instantaneous, for us) operation completes,
+ * and leaves ENCACHE/config bits set. A plain RAM stub would leave GO set
+ * forever (the SM's "wait for GO to clear" loop would hang); a zero-return
+ * stub would leave ENCACHE clear (an "is cache enabled" check would hang).
+ * So CCR persists everything except the command bits, which read back 0.
+ * The line-maintenance registers (CLCR/CSAR/CCVR) are plain storage.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/core/sysbus.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+#define TYPE_IMX95_XCACHE "imx95.xcache"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX95XCacheState, IMX95_XCACHE)
+
+/* Each instance owns 0x800 (the two M33 instances are 0x800 apart). */
+#define IMX95_XCACHE_REG_SIZE   0x800
+
+#define XCACHE_CCR              0x00
+#define XCACHE_CLCR             0x04
+#define XCACHE_CSAR             0x08
+#define XCACHE_CCVR             0x0C
+
+/* CCR bits that self-clear when the cache command completes. */
+#define CCR_GO                  0x80000000u
+#define CCR_PUSHW1              0x08000000u
+#define CCR_INVW1               0x04000000u
+#define CCR_PUSHW0              0x02000000u
+#define CCR_INVW0               0x01000000u
+#define CCR_CMD_BITS \
+    (CCR_GO | CCR_PUSHW1 | CCR_INVW1 | CCR_PUSHW0 | CCR_INVW0)
+
+struct IMX95XCacheState {
+    SysBusDevice    parent_obj;
+    MemoryRegion    iomem;
+
+    uint32_t        ccr;
+    uint32_t        clcr;
+    uint32_t        csar;
+    uint32_t        ccvr;
+};
+
+static uint64_t imx95_xcache_read(void *opaque, hwaddr offset, unsigned size)
+{
+    IMX95XCacheState *s = opaque;
+
+    trace_imx95_xcache_read(offset);
+
+    switch (offset) {
+    case XCACHE_CCR:
+        return s->ccr;
+    case XCACHE_CLCR:
+        return s->clcr;
+    case XCACHE_CSAR:
+        return s->csar;
+    case XCACHE_CCVR:
+        return s->ccvr;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad read offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+        return 0;
+    }
+}
+
+static void imx95_xcache_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    IMX95XCacheState *s = opaque;
+
+    trace_imx95_xcache_write(offset, value);
+
+    switch (offset) {
+    case XCACHE_CCR:
+        /* Command bits complete instantly: store everything else. */
+        s->ccr = (uint32_t)value & ~CCR_CMD_BITS;
+        break;
+    case XCACHE_CLCR:
+        s->clcr = value;
+        break;
+    case XCACHE_CSAR:
+        s->csar = value;
+        break;
+    case XCACHE_CCVR:
+        s->ccvr = 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 const MemoryRegionOps imx95_xcache_ops = {
+    .read = imx95_xcache_read,
+    .write = imx95_xcache_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_xcache_reset_hold(Object *obj, ResetType type)
+{
+    IMX95XCacheState *s = IMX95_XCACHE(obj);
+
+    s->ccr = 0;
+    s->clcr = 0;
+    s->csar = 0;
+    s->ccvr = 0;
+}
+
+static void imx95_xcache_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    IMX95XCacheState *s = IMX95_XCACHE(obj);
+
+    memory_region_init_io(&s->iomem, obj, &imx95_xcache_ops, s,
+                          TYPE_IMX95_XCACHE, IMX95_XCACHE_REG_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx95_xcache = {
+    .name = TYPE_IMX95_XCACHE,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32(ccr, IMX95XCacheState),
+        VMSTATE_UINT32(clcr, IMX95XCacheState),
+        VMSTATE_UINT32(csar, IMX95XCacheState),
+        VMSTATE_UINT32(ccvr, IMX95XCacheState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void imx95_xcache_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->vmsd = &vmstate_imx95_xcache;
+    rc->phases.hold = imx95_xcache_reset_hold;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->desc = "NXP i.MX 95 XCACHE controller (stub)";
+}
+
+static const TypeInfo imx95_xcache_info = {
+    .name           = TYPE_IMX95_XCACHE,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(IMX95XCacheState),
+    .instance_init  = imx95_xcache_init,
+    .class_init     = imx95_xcache_class_init,
+};
+
+static void imx95_xcache_register_types(void)
+{
+    type_register_static(&imx95_xcache_info);
+}
+
+type_init(imx95_xcache_register_types)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 0b7f5e4382d..d7d283a191b 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -178,3 +178,5 @@ system_ss.add(when: 'CONFIG_IMX95_ANATOP', if_true: files('imx95_anatop.c'))
 system_ss.add(when: 'CONFIG_IMX95_AONMIX', if_true: files('imx95_aonmix.c'))
 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'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 15fab0596c2..0555b15a1f3 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -458,3 +458,11 @@ imx95_aonmix_m7_gate(int run) "M7 wait gate -> run=%d"
 imx95_gpc_mode(uint64_t offset, uint32_t target) "CMC_MODE_CTRL off 0x%" PRIx64 " target %u"
 imx95_src_m7mix_release(void) "SRC_GEN.SCR M7MIX reset released"
 imx95_src_slice_ctrl(uint64_t offset, uint32_t value) "SLICE_SW_CTRL off 0x%" PRIx64 " <- 0x%08x"
+imx95_xcache_read(uint64_t offset) "read off 0x%" PRIx64
+imx95_xcache_write(uint64_t offset, uint64_t value) "write off 0x%" PRIx64 " <- 0x%08" PRIx64
+pf09_reg_read(uint8_t reg, uint8_t val) "PF09 reg 0x%02x -> 0x%02x"
+pf09_reg_write(uint8_t reg, uint8_t val) "PF09 reg 0x%02x <- 0x%02x"
+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"
-- 
2.34.1



  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 ` [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 ` Kyle Fox [this message]
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-13-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