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>,
	Peter Maydell <peter.maydell@linaro.org>,
	qemu-arm@nongnu.org (open list:ARM TCG CPUs)
Subject: [PATCH 15/16] hw/arm: add i.MX 95 19x19 EVK board
Date: Wed, 19 Aug 2026 21:48:33 -0500	[thread overview]
Message-ID: <20260820024834.3286721-16-kylefoxaustin.github@gmail.com> (raw)
In-Reply-To: <20260820024834.3286721-1-kylefoxaustin.github@gmail.com>

The i.MX 95 19x19 EVK board (machine type imx95-19x19-evk).
Instantiates the SoC, sets up the LPDDR5 DRAM, and provides the direct
-kernel/-dtb/-initrd Linux boot path alongside the System Manager
firmware loaded on the M33. This is the user-facing machine type.

Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
 hw/arm/Kconfig     |   7 +++
 hw/arm/imx95-evk.c | 136 +++++++++++++++++++++++++++++++++++++++++++++
 hw/arm/meson.build |   1 +
 3 files changed, 144 insertions(+)
 create mode 100644 hw/arm/imx95-evk.c

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7f1c0723ec0..d93808a48ee 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -764,3 +764,10 @@ config FSL_IMX95
     select IMX_LPI2C
     select SDHCI
     select UNIMP
+
+config FSL_IMX95_EVK
+    bool
+    default y
+    depends on AARCH64
+    depends on TCG
+    select FSL_IMX95
diff --git a/hw/arm/imx95-evk.c b/hw/arm/imx95-evk.c
new file mode 100644
index 00000000000..470ca112376
--- /dev/null
+++ b/hw/arm/imx95-evk.c
@@ -0,0 +1,136 @@
+/*
+ * NXP i.MX 95 19x19 Evaluation Kit (LPDDR5) - QEMU machine
+ *
+ * Modeled on hw/arm/imx8mp-evk.c by Bernhard Beschow
+ *
+ * Copyright (c) 2026, Kyle Fox
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Instantiates the SoC, attaches DDR, and hands control to
+ * arm_load_kernel() so -kernel works.
+ */
+
+#include "qemu/osdep.h"
+#include "system/address-spaces.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/fsl-imx95.h"
+#include "hw/arm/machines-qom.h"
+#include "hw/core/boards.h"
+#include "hw/core/qdev-properties.h"
+#include "system/kvm.h"
+#include "system/qtest.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+static void imx95_evk_init(MachineState *machine)
+{
+    static struct arm_boot_info boot_info;
+    FslImx95State *s;
+
+    if (kvm_enabled()) {
+        error_report("The imx95-19x19-evk machine requires TCG: it emulates "
+                     "Cortex-M33 and Cortex-M7 cores that KVM cannot run");
+        exit(1);
+    }
+
+    if (machine->ram_size > FSL_IMX95_RAM_SIZE_MAX) {
+        error_report("RAM size " RAM_ADDR_FMT
+                     " above max supported (0x%" PRIx64 ")",
+                     machine->ram_size, (uint64_t)FSL_IMX95_RAM_SIZE_MAX);
+        exit(1);
+    }
+
+    /*
+     * The board presets the DTB at RAM_START + 128 MiB and the initrd at
+     * RAM_START + 256 MiB (see below), so require enough RAM to hold them.
+     */
+    if (machine->ram_size < FSL_IMX95_RAM_SIZE_MIN) {
+        error_report("RAM size " RAM_ADDR_FMT
+                     " below min supported (0x%" PRIx64 ")",
+                     machine->ram_size, (uint64_t)FSL_IMX95_RAM_SIZE_MIN);
+        exit(1);
+    }
+
+    boot_info = (struct arm_boot_info) {
+        .loader_start = FSL_IMX95_RAM_START,
+        .board_id     = -1,
+        .ram_size     = machine->ram_size,
+        .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
+        /*
+         * The default arm_load_kernel() heuristic lands the initrd (and the
+         * DTB right after it) at loader_start + 128 MiB == 0x88000000. That
+         * is exactly where the NXP BSP device tree places the Cortex-M7
+         * remoteproc carveout (vdev vrings + rsc-table @0x88220000). The
+         * collision makes Linux reserve those pages for the initrd/FDT, so
+         * the later reserved-memory no-map pass fails (-EBUSY) and imx-rproc
+         * cannot ioremap the rsc-table (probe fails with -ENOMEM). Force the
+         * initrd/DTB up to 0x90000000, in the free gap above the M7 carveout
+         * and below the GPU/VPU carveouts at 0xa0000000.
+         */
+        .initrd_start = FSL_IMX95_RAM_START + 256 * MiB,
+    };
+
+    s = FSL_IMX95(object_new(TYPE_FSL_IMX95));
+    object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal);
+
+    memory_region_add_subregion(get_system_memory(), FSL_IMX95_RAM_START,
+                                machine->ram);
+
+    if (!qtest_enabled()) {
+        arm_load_kernel(&s->cpu[0], machine, &boot_info);
+
+        /*
+         * arm_load_kernel() registers its boot reset hook on every CPU in
+         * the system and treats all non-boot cores as A-profile PSCI
+         * secondaries. That is correct for the five A55 secondaries, but
+         * the Cortex-M33 SM core and the Cortex-M7 RT core are not part of
+         * the A55 boot flow - each boots from its own ITCM vector table.
+         * Detach them from the A-profile boot machinery so their reset just
+         * runs the normal M-profile vector-table reset. Whether each then
+         * actually runs is decided by the SoC's M33/M7 reset hooks (only if
+         * firmware was loaded into the respective ITCM).
+         */
+        if (s->m33.cpu) {
+            s->m33.cpu->env.boot_info = NULL;
+        }
+        if (s->m7.cpu) {
+            s->m7.cpu->env.boot_info = NULL;
+        }
+    }
+}
+
+static const char *imx95_evk_get_default_cpu_type(const MachineState *ms)
+{
+    return ARM_CPU_TYPE_NAME("cortex-a55");
+}
+
+static const char * const imx95_evk_valid_cpu_types[] = {
+    ARM_CPU_TYPE_NAME("cortex-a55"),
+    NULL
+};
+
+static void imx95_19x19_evk_machine_init(MachineClass *mc)
+{
+    mc->desc                  = "NXP i.MX 95 19x19 EVK (LPDDR5)";
+    mc->init                  = imx95_evk_init;
+    /*
+     * Total vCPUs = 6 A55 + 1 Cortex-M33 System Manager core + 1 Cortex-M7
+     * real-time core that the SoC always instantiates. TCG sizes its
+     * per-CPU context table from the resolved smp.max_cpus, which defaults
+     * to smp.cpus when -smp is not given - so both the default and the
+     * max must include the M33 and the M7, otherwise the 8th CPU's
+     * tcg_register_thread() asserts. The A55 cluster size is fixed in
+     * the SoC regardless of -smp; this count is really "A55 cluster +
+     * SM core + RT core".
+     */
+    mc->default_cpus          = FSL_IMX95_NUM_A55_CPUS + 2;
+    mc->max_cpus              = FSL_IMX95_NUM_A55_CPUS + 2;
+    mc->default_ram_id        = "imx95-19x19-evk.ram";
+    mc->default_ram_size      = 8 * GiB;   /* 19x19 EVK has 8 GiB LPDDR5 */
+    mc->get_default_cpu_type  = imx95_evk_get_default_cpu_type;
+    mc->valid_cpu_types       = imx95_evk_valid_cpu_types;
+}
+
+DEFINE_MACHINE_AARCH64("imx95-19x19-evk", imx95_19x19_evk_machine_init)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 96fef4c5b5f..cdb61fa1612 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -118,5 +118,6 @@ arm_common_ss.add(when: ['CONFIG_AXIADO_EVK', 'TARGET_AARCH64'], if_true: files(
 
 arm_common_ss.add(files('boot.c'))
 arm_common_ss.add(when: 'CONFIG_FSL_IMX95', if_true: files('fsl-imx95.c'))
+arm_common_ss.add(when: 'CONFIG_FSL_IMX95_EVK', if_true: files('imx95-evk.c'))
 
 hw_common_arch += {'arm': arm_common_ss}
-- 
2.34.1



  parent reply	other threads:[~2026-08-20  2:52 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 ` [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 ` [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 ` Kyle Fox [this message]
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-16-kylefoxaustin.github@gmail.com \
    --to=kylefoxaustin.github@gmail.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.