* [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board
@ 2025-11-10 11:22 Gaurav Sharma
2025-11-10 11:22 ` [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board Gaurav Sharma
` (13 more replies)
0 siblings, 14 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
This patch series adds support for the NXP i.MX8MM EVK (Evaluation Kit)
board to QEMU, enabling emulation of this ARM Cortex-A53 based development
platform.
The series includes:
1. Core peripheral support (CCM clock controller, Analog module)
2. GPT(General Purpose Timer) and WDT(Watchdog Timer) Emulation support
3. GPIO,I2C,SPI,USDHC and USB Emulation support
4. PCIe and ENET Controller Emulation support
5. Documentation and functional test included
Key features ported:
- Basic boot support with Linux
- UART console for serial communication
- Interrupt handling
- Clock and power management infrastructure
Testing:
- Linux kernel boots to console
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
Gaurav Sharma (13):
hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
hw/arm/fsl-imx8mm: Implemented CCM(Clock Control Module) and Analog IP
hw/arm/fsl-imx8mm: Implemented support for SNVS
hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers
hw/arm/fsl-imx8mm: Add PCIe support
hw/arm/fsl-imx8mm: Add GPIO controllers
hw/arm/fsl-imx8mm: Adding support for I2C emulation
hw/arm/fsl-imx8mm: Adding support for SPI controller
hw/arm/fsl-imx8mm: Adding support for Watchdog Timers
hw/arm/fsl-imx8mm: Adding support for General Purpose Timers
hw/arm/fsl-imx8mm: Adding support for ENET ethernet controller
hw/arm/fsl-imx8mm: Adding support for USB controller
hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
docs/system/arm/imx8mm-evk.rst | 81 +++
docs/system/target-arm.rst | 1 +
hw/arm/Kconfig | 24 +
hw/arm/fsl-imx8mm.c | 687 ++++++++++++++++++++
hw/arm/imx8mm-evk.c | 125 ++++
hw/arm/meson.build | 2 +
hw/misc/Kconfig | 6 +
hw/misc/imx8mm_analog.c | 160 +++++
hw/misc/imx8mm_ccm.c | 175 +++++
hw/misc/meson.build | 2 +
hw/timer/imx_gpt.c | 26 +
include/hw/arm/fsl-imx8mm.h | 240 +++++++
include/hw/misc/imx8mm_analog.h | 81 +++
include/hw/misc/imx8mm_ccm.h | 30 +
include/hw/timer/imx_gpt.h | 2 +
tests/functional/aarch64/meson.build | 2 +
tests/functional/aarch64/test_imx8mm_evk.py | 67 ++
17 files changed, 1711 insertions(+)
create mode 100644 docs/system/arm/imx8mm-evk.rst
create mode 100644 hw/arm/fsl-imx8mm.c
create mode 100644 hw/arm/imx8mm-evk.c
create mode 100644 hw/misc/imx8mm_analog.c
create mode 100644 hw/misc/imx8mm_ccm.c
create mode 100644 include/hw/arm/fsl-imx8mm.h
create mode 100644 include/hw/misc/imx8mm_analog.h
create mode 100644 include/hw/misc/imx8mm_ccm.h
create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
--
2.34.1
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-11 23:44 ` Bernhard Beschow
2025-11-10 11:22 ` [PATCH 02/13] hw/arm/fsl-imx8mm: Implemented CCM(Clock Control Module) and Analog IP Gaurav Sharma
` (12 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
Implemented CPUs, RAM, UARTs and Interrupt Controller
Other peripherals are represented as TYPE_UNIMPLEMENTED_DEVICE
Complete memory map of the SoC is provided.
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 70 +++++++
docs/system/target-arm.rst | 1 +
hw/arm/Kconfig | 12 ++
hw/arm/fsl-imx8mm.c | 363 +++++++++++++++++++++++++++++++++
hw/arm/imx8mm-evk.c | 107 ++++++++++
hw/arm/meson.build | 2 +
include/hw/arm/fsl-imx8mm.h | 156 ++++++++++++++
7 files changed, 711 insertions(+)
create mode 100644 docs/system/arm/imx8mm-evk.rst
create mode 100644 hw/arm/fsl-imx8mm.c
create mode 100644 hw/arm/imx8mm-evk.c
create mode 100644 include/hw/arm/fsl-imx8mm.h
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
new file mode 100644
index 0000000000..61d28ebf72
--- /dev/null
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -0,0 +1,70 @@
+NXP i.MX 8MM Evaluation Kit (``imx8mm-evk``)
+================================================
+
+The ``imx8mm-evk`` machine models the i.MX 8M Plus Evaluation Kit, based on an
+i.MX 8MM SoC.
+
+Supported devices
+-----------------
+
+The ``imx8mm-evk`` machine implements the following devices:
+
+ * Up to 4 Cortex-A53 cores
+ * Generic Interrupt Controller (GICv3)
+ * 4 UARTs
+
+Boot options
+------------
+
+The ``imx8mm-evk`` machine can start a Linux kernel directly using the standard
+``-kernel`` functionality.
+
+Direct Linux Kernel Boot
+''''''''''''''''''''''''
+
+Probably the easiest way to get started with a whole Linux system on the machine
+is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
+of writing and involves two steps. First run the following commands in the
+toplevel directory of the Buildroot source tree:
+
+.. code-block:: bash
+
+ $ make freescale_imx8mmevk_defconfig
+ $ make
+
+Once finished successfully there is an ``output/image`` subfolder. Navigate into
+it and resize the SD card image to a power of two:
+
+.. code-block:: bash
+
+ $ qemu-img resize sdcard.img 256M
+
+Now that everything is prepared the machine can be started as follows:
+
+.. code-block:: bash
+
+ $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 3G \
+ -display none -serial null -serial stdio \
+ -kernel Image \
+ -dtb imx8mm-evk.dtb \
+ -append "root=/dev/mmcblk2p2" \
+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
+
+
+KVM Acceleration
+----------------
+
+To enable hardware-assisted acceleration via KVM, append
+``-accel kvm -cpu host`` to the command line. While this speeds up performance
+significantly, be aware of the following limitations:
+
+* The ``imx8mm-evk`` machine is not included under the "virtualization use case"
+ of :doc:`QEMU's security policy </system/security>`. This means that you
+ should not trust that it can contain malicious guests, whether it is run
+ using TCG or KVM. If you don't trust your guests and you're relying on QEMU to
+ be the security boundary, you want to choose another machine such as ``virt``.
+* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
+ This is a limitation of KVM and may not work with guests with a tight
+ dependency on Cortex-A53.
+* No EL2 and EL3 exception levels are available which is also a KVM limitation.
+ Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index a96d1867df..d6a4b5bb00 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -97,6 +97,7 @@ Board-specific documentation
arm/mcimx6ul-evk
arm/mcimx7d-sabre
arm/imx8mp-evk
+ arm/imx8mm-evk
arm/orangepi
arm/raspi
arm/collie
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 0cdeb60f1f..7c66f3c3cd 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -626,6 +626,18 @@ config FSL_IMX8MP_EVK
depends on TCG || KVM
select FSL_IMX8MP
+config FSL_IMX8MM
+ bool
+ select ARM_GIC
+ select IMX
+
+config FSL_IMX8MM_EVK
+ bool
+ default y
+ depends on AARCH64
+ depends on TCG || KVM
+ select FSL_IMX8MM
+
config ARM_SMMUV3
bool
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
new file mode 100644
index 0000000000..9c8acc1e99
--- /dev/null
+++ b/hw/arm/fsl-imx8mm.c
@@ -0,0 +1,363 @@
+/*
+ * i.MX 8MM SoC Implementation
+ *
+ * Based on hw/arm/fsl-imx6.c
+ *
+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "system/address-spaces.h"
+#include "hw/arm/bsa.h"
+#include "hw/arm/fsl-imx8mm.h"
+#include "hw/misc/unimp.h"
+#include "hw/boards.h"
+#include "system/kvm.h"
+#include "system/system.h"
+#include "target/arm/cpu.h"
+#include "target/arm/cpu-qom.h"
+#include "target/arm/kvm_arm.h"
+#include "qapi/error.h"
+#include "qobject/qlist.h"
+
+static const struct {
+ hwaddr addr;
+ size_t size;
+ const char *name;
+} fsl_imx8mm_memmap[] = {
+ [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
+ [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
+ [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
+ [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
+ [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
+ [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
+ [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
+ [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
+ [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
+ [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
+ [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
+ [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
+ [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
+ [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
+ [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
+ [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
+ [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
+ [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
+ [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
+ [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
+
+ /* AIPS-4 Begin */
+ [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
+ [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
+ [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
+ [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
+ [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
+ [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
+ [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
+ /* AIPS-4 End */
+
+ [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
+
+ /* AIPS-3 Begin */
+ [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
+ [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
+ [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
+ [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
+ [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
+ [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
+ [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
+ [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
+ [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
+ [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
+ [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
+ [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
+ [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
+ [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
+ [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
+ [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
+ [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
+ [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
+ [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
+ [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
+ [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
+ [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
+ [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
+ /* AIPS-3 End */
+
+ /* AIPS-2 Begin */
+ [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
+ [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
+ [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
+ [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
+ [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
+ [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
+ [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
+ [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
+ [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
+ [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
+ [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
+ [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
+ [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
+ [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
+ /* AIPS-2 End */
+
+ /* AIPS-1 Begin */
+ [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
+ [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
+ [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
+ [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
+ [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
+ [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
+ [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
+ [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
+ [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
+ [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
+ [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
+ [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
+ [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
+ [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
+ [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
+ [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
+ [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
+ [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
+ [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
+ [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
+ [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
+ [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
+ [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
+ [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
+ [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
+ [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
+ [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
+ [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
+ [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
+ [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
+ [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
+ [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
+ [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
+
+ /* AIPS-1 End */
+
+ [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
+ [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
+ [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
+ [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
+ [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
+ [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
+ [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
+ [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
+ [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
+ [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
+};
+
+static void fsl_imx8mm_init(Object *obj)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ FslImx8mmState *s = FSL_IMX8MM(obj);
+ const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
+ int i;
+
+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
+ g_autofree char *name = g_strdup_printf("cpu%d", i);
+ object_initialize_child(obj, name, &s->cpu[i], cpu_type);
+ }
+
+ object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
+
+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
+ }
+
+}
+
+static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ FslImx8mmState *s = FSL_IMX8MM(dev);
+ DeviceState *gicdev = DEVICE(&s->gic);
+ int i;
+
+ if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
+ TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
+ return;
+ }
+
+ /* CPUs */
+ for (i = 0; i < ms->smp.cpus; i++) {
+ /* On uniprocessor, the CBAR is set to 0 */
+ if (ms->smp.cpus > 1 &&
+ object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
+ &error_abort);
+ }
+
+ /*
+ * CNTFID0 base frequency in Hz of system counter
+ */
+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
+ &error_abort);
+
+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
+ !kvm_enabled(), &error_abort);
+ }
+
+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
+ !kvm_enabled(), &error_abort);
+ }
+
+ if (i) {
+ /*
+ * Secondary CPUs start in powered-down state (and can be
+ * powered up via the SRC system reset controller)
+ */
+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
+ true, &error_abort);
+ }
+
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
+ return;
+ }
+ }
+
+ /* GIC */
+ {
+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
+ QList *redist_region_count;
+ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
+
+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
+ qdev_prop_set_uint32(gicdev, "num-irq",
+ FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
+ redist_region_count = qlist_new();
+ qlist_append_int(redist_region_count, ms->smp.cpus);
+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
+ object_property_set_link(OBJECT(&s->gic), "sysmem",
+ OBJECT(get_system_memory()), &error_fatal);
+ if (!sysbus_realize(gicsbd, errp)) {
+ return;
+ }
+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
+ sysbus_mmio_map(gicsbd, 1, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
+
+ /*
+ * Wire the outputs from each CPU's generic timer and the GICv3
+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
+ */
+ for (i = 0; i < ms->smp.cpus; i++) {
+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
+ int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
+ qemu_irq irq;
+
+ /*
+ * Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs.
+ */
+ static const int timer_irqs[] = {
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
+ };
+
+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
+ qdev_connect_gpio_out(cpudev, j, irq);
+ }
+
+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
+ 0, irq);
+
+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
+
+ sysbus_connect_irq(gicsbd, i,
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+ sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+ sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+
+ if (kvm_enabled()) {
+ if (pmu) {
+ assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
+ if (kvm_irqchip_in_kernel()) {
+ kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
+ }
+ kvm_arm_pmu_init(&s->cpu[i]);
+ }
+ }
+ }
+ }
+
+ /* UARTs */
+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq;
+ } serial_table[FSL_IMX8MM_NUM_UARTS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
+ };
+
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
+ }
+
+ /* Unimplemented devices */
+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
+ switch (i) {
+ case FSL_IMX8MM_GIC_DIST:
+ case FSL_IMX8MM_GIC_REDIST:
+ case FSL_IMX8MM_RAM:
+ case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
+ /* device implemented and treated above */
+ break;
+
+ default:
+ create_unimplemented_device(fsl_imx8mm_memmap[i].name,
+ fsl_imx8mm_memmap[i].addr,
+ fsl_imx8mm_memmap[i].size);
+ break;
+ }
+ }
+}
+
+static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = fsl_imx8mm_realize;
+
+ dc->desc = "i.MX 8MM SoC";
+}
+
+static const TypeInfo fsl_imx8mm_types[] = {
+ {
+ .name = TYPE_FSL_IMX8MM,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FslImx8mmState),
+ .instance_init = fsl_imx8mm_init,
+ .class_init = fsl_imx8mm_class_init,
+ },
+};
+
+DEFINE_TYPES(fsl_imx8mm_types)
diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c
new file mode 100644
index 0000000000..cfb42fe464
--- /dev/null
+++ b/hw/arm/imx8mm-evk.c
@@ -0,0 +1,107 @@
+/*
+ * NXP i.MX 8MM Evaluation Kit System Emulation
+ *
+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "system/address-spaces.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/fsl-imx8mm.h"
+#include "hw/arm/machines-qom.h"
+#include "hw/boards.h"
+#include "hw/qdev-properties.h"
+#include "system/kvm.h"
+#include "system/qtest.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include <libfdt.h>
+
+static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info, void *fdt)
+{
+ int i, offset;
+
+ /* Temporarily disable following nodes until they are implemented */
+ const char *nodes_to_remove[] = {
+ "nxp,imx8mm-fspi",
+ };
+
+ for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
+ const char *dev_str = nodes_to_remove[i];
+
+ offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
+ while (offset >= 0) {
+ fdt_nop_node(fdt, offset);
+ offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
+ }
+ }
+
+ /* Remove cpu-idle-states property from CPU nodes */
+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
+ while (offset >= 0) {
+ fdt_nop_property(fdt, offset, "cpu-idle-states");
+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
+ }
+
+ if (kvm_enabled()) {
+ /* Use system counter frequency from host CPU to fix time in guest */
+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
+ while (offset >= 0) {
+ fdt_nop_property(fdt, offset, "clock-frequency");
+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
+ }
+ }
+}
+
+static void imx8mm_evk_init(MachineState *machine)
+{
+ static struct arm_boot_info boot_info;
+ FslImx8mmState *s;
+
+ if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
+ machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
+ exit(1);
+ }
+
+ boot_info = (struct arm_boot_info) {
+ .loader_start = FSL_IMX8MM_RAM_START,
+ .board_id = -1,
+ .ram_size = machine->ram_size,
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
+ .modify_dtb = imx8mm_evk_modify_dtb,
+ };
+
+ s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
+ 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_IMX8MM_RAM_START,
+ machine->ram);
+
+ if (!qtest_enabled()) {
+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
+ }
+}
+
+static const char *imx8mm_evk_get_default_cpu_type(const MachineState *ms)
+{
+ if (kvm_enabled()) {
+ return ARM_CPU_TYPE_NAME("host");
+ }
+
+ return ARM_CPU_TYPE_NAME("cortex-a53");
+}
+
+static void imx8mm_evk_machine_init(MachineClass *mc)
+{
+ mc->desc = "NXP i.MX 8MM EVK Board";
+ mc->init = imx8mm_evk_init;
+ mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
+ mc->default_ram_id = "imx8mm-evk.ram";
+ mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type;
+}
+
+DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index aeaf654790..12ecb824cc 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true: files('fsl-imx8mm.c'))
+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true: files('imx8mm-evk.c'))
arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
arm_common_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
arm_common_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
new file mode 100644
index 0000000000..aa954ea00b
--- /dev/null
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -0,0 +1,156 @@
+/*
+ * i.MX 8MM SoC Definitions
+ *
+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef FSL_IMX8MM_H
+#define FSL_IMX8MM_H
+
+#include "cpu.h"
+#include "hw/char/imx_serial.h"
+#include "hw/intc/arm_gicv3_common.h"
+#include "qom/object.h"
+#include "qemu/units.h"
+
+#define TYPE_FSL_IMX8MM "fsl-imx8mm"
+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
+
+#define FSL_IMX8MM_RAM_START 0x40000000
+#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
+
+enum FslImx8mmConfiguration {
+ FSL_IMX8MM_NUM_CPUS = 4,
+ FSL_IMX8MM_NUM_IRQS = 128,
+ FSL_IMX8MM_NUM_UARTS = 4,
+};
+
+struct FslImx8mmState {
+ SysBusDevice parent_obj;
+
+ ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
+ GICv3State gic;
+ IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
+};
+
+enum FslImx8mmMemoryRegions {
+ FSL_IMX8MM_A53_DAP,
+ FSL_IMX8MM_AIPS1_CONFIGURATION,
+ FSL_IMX8MM_AIPS2_CONFIGURATION,
+ FSL_IMX8MM_AIPS3_CONFIGURATION,
+ FSL_IMX8MM_AIPS4_CONFIGURATION,
+ FSL_IMX8MM_ANA_OSC,
+ FSL_IMX8MM_ANA_PLL,
+ FSL_IMX8MM_ANA_TSENSOR,
+ FSL_IMX8MM_APBH_DMA,
+ FSL_IMX8MM_BOOT_ROM,
+ FSL_IMX8MM_BOOT_ROM_PROTECTED,
+ FSL_IMX8MM_CAAM,
+ FSL_IMX8MM_CAAM_MEM,
+ FSL_IMX8MM_CCM,
+ FSL_IMX8MM_CSU,
+ FSL_IMX8MM_DDR_CTL,
+ FSL_IMX8MM_DDR_PERF_MON,
+ FSL_IMX8MM_DDR_PHY,
+ FSL_IMX8MM_DDR_PHY_BROADCAST,
+ FSL_IMX8MM_ECSPI1,
+ FSL_IMX8MM_ECSPI2,
+ FSL_IMX8MM_ECSPI3,
+ FSL_IMX8MM_ENET1,
+ FSL_IMX8MM_GIC_DIST,
+ FSL_IMX8MM_GIC_REDIST,
+ FSL_IMX8MM_GPC,
+ FSL_IMX8MM_GPIO1,
+ FSL_IMX8MM_GPIO2,
+ FSL_IMX8MM_GPIO3,
+ FSL_IMX8MM_GPIO4,
+ FSL_IMX8MM_GPIO5,
+ FSL_IMX8MM_GPT1,
+ FSL_IMX8MM_GPT2,
+ FSL_IMX8MM_GPT3,
+ FSL_IMX8MM_GPT4,
+ FSL_IMX8MM_GPT5,
+ FSL_IMX8MM_GPT6,
+ FSL_IMX8MM_GPU2D,
+ FSL_IMX8MM_I2C1,
+ FSL_IMX8MM_I2C2,
+ FSL_IMX8MM_I2C3,
+ FSL_IMX8MM_I2C4,
+ FSL_IMX8MM_INTERCONNECT,
+ FSL_IMX8MM_IOMUXC,
+ FSL_IMX8MM_IOMUXC_GPR,
+ FSL_IMX8MM_MEDIA_BLK_CTL,
+ FSL_IMX8MM_LCDIF,
+ FSL_IMX8MM_MIPI_CSI,
+ FSL_IMX8MM_MIPI_DSI,
+ FSL_IMX8MM_MU_A,
+ FSL_IMX8MM_MU_B,
+ FSL_IMX8MM_OCOTP_CTRL,
+ FSL_IMX8MM_OCRAM,
+ FSL_IMX8MM_OCRAM_S,
+ FSL_IMX8MM_PCIE1,
+ FSL_IMX8MM_PCIE1_MEM,
+ FSL_IMX8MM_PCIE_PHY1,
+ FSL_IMX8MM_PERFMON1,
+ FSL_IMX8MM_PERFMON2,
+ FSL_IMX8MM_PWM1,
+ FSL_IMX8MM_PWM2,
+ FSL_IMX8MM_PWM3,
+ FSL_IMX8MM_PWM4,
+ FSL_IMX8MM_QOSC,
+ FSL_IMX8MM_QSPI,
+ FSL_IMX8MM_QSPI1_RX_BUFFER,
+ FSL_IMX8MM_QSPI1_TX_BUFFER,
+ FSL_IMX8MM_QSPI_MEM,
+ FSL_IMX8MM_RAM,
+ FSL_IMX8MM_RDC,
+ FSL_IMX8MM_SAI1,
+ FSL_IMX8MM_SAI2,
+ FSL_IMX8MM_SAI3,
+ FSL_IMX8MM_SAI5,
+ FSL_IMX8MM_SAI6,
+ FSL_IMX8MM_SDMA1,
+ FSL_IMX8MM_SDMA2,
+ FSL_IMX8MM_SDMA3,
+ FSL_IMX8MM_SEMAPHORE1,
+ FSL_IMX8MM_SEMAPHORE2,
+ FSL_IMX8MM_SEMAPHORE_HS,
+ FSL_IMX8MM_SNVS_HP,
+ FSL_IMX8MM_SPBA1,
+ FSL_IMX8MM_SRC,
+ FSL_IMX8MM_SYSCNT_CMP,
+ FSL_IMX8MM_SYSCNT_CTRL,
+ FSL_IMX8MM_SYSCNT_RD,
+ FSL_IMX8MM_TCM_DTCM,
+ FSL_IMX8MM_TCM_ITCM,
+ FSL_IMX8MM_TZASC,
+ FSL_IMX8MM_UART1,
+ FSL_IMX8MM_UART2,
+ FSL_IMX8MM_UART3,
+ FSL_IMX8MM_UART4,
+ FSL_IMX8MM_USB1,
+ FSL_IMX8MM_USB2,
+ FSL_IMX8MM_USB1_OTG,
+ FSL_IMX8MM_USB2_OTG,
+ FSL_IMX8MM_USDHC1,
+ FSL_IMX8MM_USDHC2,
+ FSL_IMX8MM_USDHC3,
+ FSL_IMX8MM_VPU,
+ FSL_IMX8MM_VPU_BLK_CTRL,
+ FSL_IMX8MM_VPU_G1_DECODER,
+ FSL_IMX8MM_VPU_G2_DECODER,
+ FSL_IMX8MM_WDOG1,
+ FSL_IMX8MM_WDOG2,
+ FSL_IMX8MM_WDOG3,
+};
+
+enum FslImx8mmIrqs {
+ FSL_IMX8MM_UART1_IRQ = 26,
+ FSL_IMX8MM_UART2_IRQ = 27,
+ FSL_IMX8MM_UART3_IRQ = 28,
+ FSL_IMX8MM_UART4_IRQ = 29,
+};
+
+#endif /* FSL_IMX8MM_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 02/13] hw/arm/fsl-imx8mm: Implemented CCM(Clock Control Module) and Analog IP
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
2025-11-10 11:22 ` [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 11:22 ` [PATCH 03/13] hw/arm/fsl-imx8mm: Implemented support for SNVS Gaurav Sharma
` (11 subsequent siblings)
13 siblings, 0 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
Implemented Analog device model
Implemented CCM device model
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 2 +
hw/arm/fsl-imx8mm.c | 20 ++++
hw/misc/Kconfig | 6 ++
hw/misc/imx8mm_analog.c | 160 +++++++++++++++++++++++++++++
hw/misc/imx8mm_ccm.c | 175 ++++++++++++++++++++++++++++++++
hw/misc/meson.build | 2 +
include/hw/arm/fsl-imx8mm.h | 4 +
include/hw/misc/imx8mm_analog.h | 81 +++++++++++++++
include/hw/misc/imx8mm_ccm.h | 30 ++++++
10 files changed, 481 insertions(+)
create mode 100644 hw/misc/imx8mm_analog.c
create mode 100644 hw/misc/imx8mm_ccm.c
create mode 100644 include/hw/misc/imx8mm_analog.h
create mode 100644 include/hw/misc/imx8mm_ccm.h
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index 61d28ebf72..1cdfa153cb 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -12,6 +12,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* Up to 4 Cortex-A53 cores
* Generic Interrupt Controller (GICv3)
* 4 UARTs
+ * Clock Tree
Boot options
------------
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7c66f3c3cd..314ffcd315 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -629,6 +629,8 @@ config FSL_IMX8MP_EVK
config FSL_IMX8MM
bool
select ARM_GIC
+ select FSL_IMX8MM_ANALOG
+ select FSL_IMX8MM_CCM
select IMX
config FSL_IMX8MM_EVK
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 9c8acc1e99..248eebfbce 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -166,6 +166,10 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MM_CCM);
+
+ object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MM_ANALOG);
+
for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
@@ -300,6 +304,20 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
}
}
+ /* CCM */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
+ fsl_imx8mm_memmap[FSL_IMX8MM_CCM].addr);
+
+ /* Analog */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
+ fsl_imx8mm_memmap[FSL_IMX8MM_ANA_PLL].addr);
+
/* UARTs */
for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
struct {
@@ -325,6 +343,8 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
/* Unimplemented devices */
for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
switch (i) {
+ case FSL_IMX8MM_ANA_PLL:
+ case FSL_IMX8MM_CCM:
case FSL_IMX8MM_GIC_DIST:
case FSL_IMX8MM_GIC_REDIST:
case FSL_IMX8MM_RAM:
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index fccd735c24..56248ba3c2 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -96,6 +96,12 @@ config FSL_IMX8MP_ANALOG
config FSL_IMX8MP_CCM
bool
+config FSL_IMX8MM_ANALOG
+ bool
+
+config FSL_IMX8MM_CCM
+ bool
+
config STM32_RCC
bool
diff --git a/hw/misc/imx8mm_analog.c b/hw/misc/imx8mm_analog.c
new file mode 100644
index 0000000000..d6ba1344d3
--- /dev/null
+++ b/hw/misc/imx8mm_analog.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2025 Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * i.MX 8MM ANALOG IP block emulation code
+ *
+ * Based on hw/misc/imx7_ccm.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx8mm_analog.h"
+#include "migration/vmstate.h"
+
+#define ANALOG_PLL_LOCK BIT(31)
+
+static void imx8mm_analog_reset(DeviceState *dev)
+{
+ IMX8MMAnalogState *s = IMX8MM_ANALOG(dev);
+
+ memset(s->analog, 0, sizeof(s->analog));
+
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
+ s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
+ s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
+ s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
+ s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
+ s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
+ s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
+ s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
+ s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
+ s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
+ s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
+ s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
+ s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
+ s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
+ s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
+ s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa030;
+ s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
+ s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
+ s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
+ s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
+ s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
+ s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
+ s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
+ s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
+ s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
+ s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
+ s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
+ s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
+ s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
+ s->analog[ANALOG_DIGPROG] = 0x00824010;
+
+ /* all PLLs need to be locked */
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
+}
+
+static uint64_t imx8mm_analog_read(void *opaque, hwaddr offset, unsigned size)
+{
+ IMX8MMAnalogState *s = opaque;
+
+ return s->analog[offset >> 2];
+}
+
+static void imx8mm_analog_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ IMX8MMAnalogState *s = opaque;
+
+ if (offset >> 2 == ANALOG_DIGPROG) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Guest write to read-only ANALOG_DIGPROG register\n");
+ } else {
+ s->analog[offset >> 2] = value;
+ }
+}
+
+static const struct MemoryRegionOps imx8mm_analog_ops = {
+ .read = imx8mm_analog_read,
+ .write = imx8mm_analog_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx8mm_analog_init(Object *obj)
+{
+ IMX8MMAnalogState *s = IMX8MM_ANALOG(obj);
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX8MM_ANALOG, 0x10000);
+
+ memory_region_init_io(&s->mmio.analog, obj, &imx8mm_analog_ops, s,
+ TYPE_IMX8MM_ANALOG, sizeof(s->analog));
+ memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
+
+ sysbus_init_mmio(sd, &s->mmio.container);
+}
+
+static const VMStateDescription imx8mm_analog_vmstate = {
+ .name = TYPE_IMX8MM_ANALOG,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(analog, IMX8MMAnalogState, ANALOG_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void imx8mm_analog_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_legacy_reset(dc, imx8mm_analog_reset);
+ dc->vmsd = &imx8mm_analog_vmstate;
+ dc->desc = "i.MX 8MM Analog Module";
+}
+
+static const TypeInfo imx8mm_analog_types[] = {
+ {
+ .name = TYPE_IMX8MM_ANALOG,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX8MMAnalogState),
+ .instance_init = imx8mm_analog_init,
+ .class_init = imx8mm_analog_class_init,
+ }
+};
+
+DEFINE_TYPES(imx8mm_analog_types);
diff --git a/hw/misc/imx8mm_ccm.c b/hw/misc/imx8mm_ccm.c
new file mode 100644
index 0000000000..352a6ee188
--- /dev/null
+++ b/hw/misc/imx8mm_ccm.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2025 Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * i.MX 8MM CCM IP block emulation code
+ *
+ * Based on hw/misc/imx7_ccm.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx8mm_ccm.h"
+#include "migration/vmstate.h"
+
+#include "trace.h"
+
+#define CKIH_FREQ 16000000 /* 16MHz crystal input */
+
+static void imx8mm_ccm_reset(DeviceState *dev)
+{
+ IMX8MMCCMState *s = IMX8MM_CCM(dev);
+
+ memset(s->ccm, 0, sizeof(s->ccm));
+}
+
+#define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset) ((offset) & (hwaddr)0xF)
+
+enum {
+ CCM_BITOP_NONE = 0x00,
+ CCM_BITOP_SET = 0x04,
+ CCM_BITOP_CLR = 0x08,
+ CCM_BITOP_TOG = 0x0C,
+};
+
+static uint64_t imx8mm_set_clr_tog_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ const uint32_t *mmio = opaque;
+
+ return mmio[CCM_INDEX(offset)];
+}
+
+static void imx8mm_set_clr_tog_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ const uint8_t bitop = CCM_BITOP(offset);
+ const uint32_t index = CCM_INDEX(offset);
+ uint32_t *mmio = opaque;
+
+ switch (bitop) {
+ case CCM_BITOP_NONE:
+ mmio[index] = value;
+ break;
+ case CCM_BITOP_SET:
+ mmio[index] |= value;
+ break;
+ case CCM_BITOP_CLR:
+ mmio[index] &= ~value;
+ break;
+ case CCM_BITOP_TOG:
+ mmio[index] ^= value;
+ break;
+ };
+}
+
+static const struct MemoryRegionOps imx8mm_set_clr_tog_ops = {
+ .read = imx8mm_set_clr_tog_read,
+ .write = imx8mm_set_clr_tog_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx8mm_ccm_init(Object *obj)
+{
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ IMX8MMCCMState *s = IMX8MM_CCM(obj);
+
+ memory_region_init_io(&s->iomem,
+ obj,
+ &imx8mm_set_clr_tog_ops,
+ s->ccm,
+ TYPE_IMX8MM_CCM ".ccm",
+ sizeof(s->ccm));
+
+ sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription imx8mm_ccm_vmstate = {
+ .name = TYPE_IMX8MM_CCM,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(ccm, IMX8MMCCMState, CCM_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static uint32_t imx8mm_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+ /*
+ * This function is "consumed" by GPT emulation code. Some clocks
+ * have fixed frequencies and we can provide requested frequency
+ * easily. However for CCM provided clocks (like IPG) each GPT
+ * timer can have its own clock root.
+ * This means we need additional information when calling this
+ * function to know the requester's identity.
+ */
+ uint32_t freq = 0;
+
+ switch (clock) {
+ case CLK_NONE:
+ break;
+ case CLK_32k:
+ freq = CKIL_FREQ;
+ break;
+ case CLK_HIGH:
+ freq = CKIH_FREQ;
+ break;
+ case CLK_IPG:
+ case CLK_IPG_HIGH:
+ /*
+ * For now we don't have a way to figure out the device this
+ * function is called for. Until then the IPG derived clocks
+ * are left unimplemented.
+ */
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n",
+ TYPE_IMX8MM_CCM, __func__, clock);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
+ TYPE_IMX8MM_CCM, __func__, clock);
+ break;
+ }
+
+ trace_ccm_clock_freq(clock, freq);
+
+ return freq;
+}
+
+static void imx8mm_ccm_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
+
+ device_class_set_legacy_reset(dc, imx8mm_ccm_reset);
+ dc->vmsd = &imx8mm_ccm_vmstate;
+ dc->desc = "i.MX 8MM Clock Control Module";
+
+ ccm->get_clock_frequency = imx8mm_ccm_get_clock_frequency;
+}
+
+static const TypeInfo imx8mm_ccm_types[] = {
+ {
+ .name = TYPE_IMX8MM_CCM,
+ .parent = TYPE_IMX_CCM,
+ .instance_size = sizeof(IMX8MMCCMState),
+ .instance_init = imx8mm_ccm_init,
+ .class_init = imx8mm_ccm_class_init,
+ },
+};
+
+DEFINE_TYPES(imx8mm_ccm_types);
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index b1d8d8e5d2..556daea9bc 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -57,6 +57,8 @@ system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
+system_ss.add(when: 'CONFIG_FSL_IMX8MM_ANALOG', if_true: files('imx8mm_analog.c'))
+system_ss.add(when: 'CONFIG_FSL_IMX8MM_CCM', if_true: files('imx8mm_ccm.c'))
system_ss.add(when: 'CONFIG_IMX', if_true: files(
'imx25_ccm.c',
'imx31_ccm.c',
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index aa954ea00b..0716484429 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -12,6 +12,8 @@
#include "cpu.h"
#include "hw/char/imx_serial.h"
#include "hw/intc/arm_gicv3_common.h"
+#include "hw/misc/imx8mm_analog.h"
+#include "hw/misc/imx8mm_ccm.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -32,6 +34,8 @@ struct FslImx8mmState {
ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
GICv3State gic;
+ IMX8MMCCMState ccm;
+ IMX8MMAnalogState analog;
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
};
diff --git a/include/hw/misc/imx8mm_analog.h b/include/hw/misc/imx8mm_analog.h
new file mode 100644
index 0000000000..e16e2a0cf1
--- /dev/null
+++ b/include/hw/misc/imx8mm_analog.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2025 Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * i.MX8MM ANALOG IP block emulation code
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IMX8MM_ANALOG_H
+#define IMX8MM_ANALOG_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+enum IMX8MMAnalogRegisters {
+ ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
+ ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
+ ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
+ ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
+ ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
+ ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
+ ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
+ ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
+ ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
+ ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
+ ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
+ ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
+ ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
+ ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
+ ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
+ ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
+ ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
+ ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
+ ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
+ ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
+ ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
+ ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
+ ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
+ ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
+ ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
+ ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
+ ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
+ ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
+ ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
+ ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
+ ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
+ ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
+ ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
+ ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
+ ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
+ ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
+ ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
+ ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
+ ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
+ ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
+ ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
+ ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
+ ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
+ ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
+ ANALOG_OSC_MISC_CFG = 0x124 / 4,
+ ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
+
+ ANALOG_DIGPROG = 0x800 / 4,
+ ANALOG_MAX,
+};
+
+#define TYPE_IMX8MM_ANALOG "imx8mm.analog"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MMAnalogState, IMX8MM_ANALOG)
+
+struct IMX8MMAnalogState {
+ SysBusDevice parent_obj;
+
+ struct {
+ MemoryRegion container;
+ MemoryRegion analog;
+ } mmio;
+
+ uint32_t analog[ANALOG_MAX];
+};
+
+#endif /* IMX8MM_ANALOG_H */
diff --git a/include/hw/misc/imx8mm_ccm.h b/include/hw/misc/imx8mm_ccm.h
new file mode 100644
index 0000000000..e02e25f178
--- /dev/null
+++ b/include/hw/misc/imx8mm_ccm.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Gaurav Sharma <gaurav.sharma_7@nxp.com>
+ *
+ * i.MX 8MM CCM IP block emulation code
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IMX8MM_CCM_H
+#define IMX8MM_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
+
+enum IMX8MMCCMRegisters {
+ CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
+};
+
+#define TYPE_IMX8MM_CCM "imx8mm.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MMCCMState, IMX8MM_CCM)
+
+struct IMX8MMCCMState {
+ IMXCCMState parent_obj;
+
+ MemoryRegion iomem;
+
+ uint32_t ccm[CCM_MAX];
+};
+
+#endif /* IMX8MM_CCM_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 03/13] hw/arm/fsl-imx8mm: Implemented support for SNVS
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
2025-11-10 11:22 ` [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board Gaurav Sharma
2025-11-10 11:22 ` [PATCH 02/13] hw/arm/fsl-imx8mm: Implemented CCM(Clock Control Module) and Analog IP Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 11:22 ` [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers Gaurav Sharma
` (10 subsequent siblings)
13 siblings, 0 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
SNVS contains an RTC which allows Linux to deal correctly with time
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/fsl-imx8mm.c | 10 ++++++++++
include/hw/arm/fsl-imx8mm.h | 2 ++
3 files changed, 13 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index 1cdfa153cb..e50e72bdcf 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -12,6 +12,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* Up to 4 Cortex-A53 cores
* Generic Interrupt Controller (GICv3)
* 4 UARTs
+ * Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
Boot options
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 248eebfbce..7d9707c131 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -170,6 +170,8 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MM_ANALOG);
+ object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
+
for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
@@ -340,6 +342,13 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, serial_table[i].irq));
}
+ /* SNVS */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
+ fsl_imx8mm_memmap[FSL_IMX8MM_SNVS_HP].addr);
+
/* Unimplemented devices */
for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
switch (i) {
@@ -348,6 +357,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_GIC_DIST:
case FSL_IMX8MM_GIC_REDIST:
case FSL_IMX8MM_RAM:
+ case FSL_IMX8MM_SNVS_HP:
case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
/* device implemented and treated above */
break;
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 0716484429..4fd11798a5 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -12,6 +12,7 @@
#include "cpu.h"
#include "hw/char/imx_serial.h"
#include "hw/intc/arm_gicv3_common.h"
+#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
#include "hw/misc/imx8mm_ccm.h"
#include "qom/object.h"
@@ -36,6 +37,7 @@ struct FslImx8mmState {
GICv3State gic;
IMX8MMCCMState ccm;
IMX8MMAnalogState analog;
+ IMX7SNVSState snvs;
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
};
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (2 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 03/13] hw/arm/fsl-imx8mm: Implemented support for SNVS Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:05 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 05/13] hw/arm/fsl-imx8mm: Add PCIe support Gaurav Sharma
` (9 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
It enables emulation of SD/MMC cards through a virtual SDHCI interface
The emulated SDHCI controller allows guest OS to use emulated storage as
a standard block device.
This will allow running the images such as those generated
by Buildroot.
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 1 +
hw/arm/fsl-imx8mm.c | 25 +++++++++++++++++++++++++
hw/arm/imx8mm-evk.c | 17 +++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 7 +++++++
5 files changed, 51 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index e50e72bdcf..b6dd9e758c 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -12,6 +12,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* Up to 4 Cortex-A53 cores
* Generic Interrupt Controller (GICv3)
* 4 UARTs
+ * 3 USDHC Storage Controllers
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 314ffcd315..b5eb6553f5 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -632,6 +632,7 @@ config FSL_IMX8MM
select FSL_IMX8MM_ANALOG
select FSL_IMX8MM_CCM
select IMX
+ select SDHCI
config FSL_IMX8MM_EVK
bool
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 7d9707c131..ba574fc211 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -177,6 +177,10 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
+ g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
+ object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
+ }
}
static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
@@ -342,6 +346,26 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, serial_table[i].irq));
}
+ /* USDHCs */
+ for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq;
+ } usdhc_table[FSL_IMX8MM_NUM_USDHCS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC1].addr, FSL_IMX8MM_USDHC1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC2].addr, FSL_IMX8MM_USDHC2_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC3].addr, FSL_IMX8MM_USDHC3_IRQ },
+ };
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
+ qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
+ }
+
/* SNVS */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
return;
@@ -359,6 +383,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_RAM:
case FSL_IMX8MM_SNVS_HP:
case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
+ case FSL_IMX8MM_USDHC1 ... FSL_IMX8MM_USDHC3:
/* device implemented and treated above */
break;
diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c
index cfb42fe464..a4ab910ee4 100644
--- a/hw/arm/imx8mm-evk.c
+++ b/hw/arm/imx8mm-evk.c
@@ -81,6 +81,23 @@ static void imx8mm_evk_init(MachineState *machine)
memory_region_add_subregion(get_system_memory(), FSL_IMX8MM_RAM_START,
machine->ram);
+ for (int i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
+ BusState *bus;
+ DeviceState *carddev;
+ BlockBackend *blk;
+ DriveInfo *di = drive_get(IF_SD, i, 0);
+
+ if (!di) {
+ continue;
+ }
+
+ blk = blk_by_legacy_dinfo(di);
+ bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
+ carddev = qdev_new(TYPE_SD_CARD);
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
+ }
+
if (!qtest_enabled()) {
arm_load_kernel(&s->cpu[0], machine, &boot_info);
}
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 4fd11798a5..985a0a5571 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -15,6 +15,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
#include "hw/misc/imx8mm_ccm.h"
+#include "hw/sd/sdhci.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -28,6 +29,7 @@ enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_CPUS = 4,
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
+ FSL_IMX8MM_NUM_USDHCS = 3,
};
struct FslImx8mmState {
@@ -39,6 +41,7 @@ struct FslImx8mmState {
IMX8MMAnalogState analog;
IMX7SNVSState snvs;
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
+ SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
};
enum FslImx8mmMemoryRegions {
@@ -153,6 +156,10 @@ enum FslImx8mmMemoryRegions {
};
enum FslImx8mmIrqs {
+ FSL_IMX8MM_USDHC1_IRQ = 22,
+ FSL_IMX8MM_USDHC2_IRQ = 23,
+ FSL_IMX8MM_USDHC3_IRQ = 24,
+
FSL_IMX8MM_UART1_IRQ = 26,
FSL_IMX8MM_UART2_IRQ = 27,
FSL_IMX8MM_UART3_IRQ = 28,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 05/13] hw/arm/fsl-imx8mm: Add PCIe support
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (3 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:00 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 06/13] hw/arm/fsl-imx8mm: Add GPIO controllers Gaurav Sharma
` (8 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
This enables support for Designware PCI Express Controller emulation
It provides a controlled environment to debug the linux pci subsystem
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 3 +++
hw/arm/fsl-imx8mm.c | 30 ++++++++++++++++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 10 ++++++++++
4 files changed, 44 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index b6dd9e758c..026db7c4a6 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -13,6 +13,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* Generic Interrupt Controller (GICv3)
* 4 UARTs
* 3 USDHC Storage Controllers
+ * 1 Designware PCI Express Controller
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index b5eb6553f5..6df1478c4f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -628,11 +628,14 @@ config FSL_IMX8MP_EVK
config FSL_IMX8MM
bool
+ imply PCI_DEVICES
select ARM_GIC
select FSL_IMX8MM_ANALOG
select FSL_IMX8MM_CCM
select IMX
select SDHCI
+ select PCI_EXPRESS_DESIGNWARE
+ select PCI_EXPRESS_FSL_IMX8M_PHY
config FSL_IMX8MM_EVK
bool
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index ba574fc211..ea5799b2cc 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -181,6 +181,10 @@ static void fsl_imx8mm_init(Object *obj)
g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
}
+
+ object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
+ object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
+ TYPE_FSL_IMX8M_PCIE_PHY);
}
static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
@@ -373,6 +377,30 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
fsl_imx8mm_memmap[FSL_IMX8MM_SNVS_HP].addr);
+ /* PCIe */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0,
+ fsl_imx8mm_memmap[FSL_IMX8MM_PCIE1].addr);
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTA_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTB_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTC_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTD_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_MSI_IRQ));
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
+ fsl_imx8mm_memmap[FSL_IMX8MM_PCIE_PHY1].addr);
+
/* Unimplemented devices */
for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
switch (i) {
@@ -380,6 +408,8 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_CCM:
case FSL_IMX8MM_GIC_DIST:
case FSL_IMX8MM_GIC_REDIST:
+ case FSL_IMX8MM_PCIE1:
+ case FSL_IMX8MM_PCIE_PHY1:
case FSL_IMX8MM_RAM:
case FSL_IMX8MM_SNVS_HP:
case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 985a0a5571..74a1a1349d 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -15,6 +15,8 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
#include "hw/misc/imx8mm_ccm.h"
+#include "hw/pci-host/designware.h"
+#include "hw/pci-host/fsl_imx8m_phy.h"
#include "hw/sd/sdhci.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -42,6 +44,8 @@ struct FslImx8mmState {
IMX7SNVSState snvs;
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
+ DesignwarePCIEHost pcie;
+ FslImx8mPciePhyState pcie_phy;
};
enum FslImx8mmMemoryRegions {
@@ -164,6 +168,12 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_UART2_IRQ = 27,
FSL_IMX8MM_UART3_IRQ = 28,
FSL_IMX8MM_UART4_IRQ = 29,
+
+ FSL_IMX8MM_PCI_INTA_IRQ = 122,
+ FSL_IMX8MM_PCI_INTB_IRQ = 123,
+ FSL_IMX8MM_PCI_INTC_IRQ = 124,
+ FSL_IMX8MM_PCI_INTD_IRQ = 125,
+ FSL_IMX8MM_PCI_MSI_IRQ = 127,
};
#endif /* FSL_IMX8MM_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 06/13] hw/arm/fsl-imx8mm: Add GPIO controllers
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (4 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 05/13] hw/arm/fsl-imx8mm: Add PCIe support Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:02 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 07/13] hw/arm/fsl-imx8mm: Adding support for I2C emulation Gaurav Sharma
` (7 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
Enabled GPIO controller emulation
Also updated the GPIO IRQ lines of iMX8MM
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/fsl-imx8mm.c | 54 ++++++++++++++++++++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 14 +++++++++
3 files changed, 69 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index 026db7c4a6..c55d02c1c2 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -14,6 +14,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 4 UARTs
* 3 USDHC Storage Controllers
* 1 Designware PCI Express Controller
+ * 5 GPIO Controllers
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index ea5799b2cc..222d3bac1c 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -177,6 +177,11 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
+ g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
+ }
+
for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
@@ -350,6 +355,54 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, serial_table[i].irq));
}
+ /* GPIOs */
+ for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq_low;
+ unsigned int irq_high;
+ } gpio_table[FSL_IMX8MM_NUM_GPIOS] = {
+ {
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPIO1].addr,
+ FSL_IMX8MM_GPIO1_LOW_IRQ,
+ FSL_IMX8MM_GPIO1_HIGH_IRQ
+ },
+ {
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPIO2].addr,
+ FSL_IMX8MM_GPIO2_LOW_IRQ,
+ FSL_IMX8MM_GPIO2_HIGH_IRQ
+ },
+ {
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPIO3].addr,
+ FSL_IMX8MM_GPIO3_LOW_IRQ,
+ FSL_IMX8MM_GPIO3_HIGH_IRQ
+ },
+ {
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPIO4].addr,
+ FSL_IMX8MM_GPIO4_LOW_IRQ,
+ FSL_IMX8MM_GPIO4_HIGH_IRQ
+ },
+ {
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPIO5].addr,
+ FSL_IMX8MM_GPIO5_LOW_IRQ,
+ FSL_IMX8MM_GPIO5_HIGH_IRQ
+ },
+ };
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
+ &error_abort);
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq",
+ true, &error_abort);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
+ }
+
/* USDHCs */
for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
struct {
@@ -408,6 +461,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_CCM:
case FSL_IMX8MM_GIC_DIST:
case FSL_IMX8MM_GIC_REDIST:
+ case FSL_IMX8MM_GPIO1 ... FSL_IMX8MM_GPIO5:
case FSL_IMX8MM_PCIE1:
case FSL_IMX8MM_PCIE_PHY1:
case FSL_IMX8MM_RAM:
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 74a1a1349d..d3a2d1843f 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -11,6 +11,7 @@
#include "cpu.h"
#include "hw/char/imx_serial.h"
+#include "hw/gpio/imx_gpio.h"
#include "hw/intc/arm_gicv3_common.h"
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
@@ -29,6 +30,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_CPUS = 4,
+ FSL_IMX8MM_NUM_GPIOS = 5,
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
FSL_IMX8MM_NUM_USDHCS = 3,
@@ -39,6 +41,7 @@ struct FslImx8mmState {
ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
GICv3State gic;
+ IMXGPIOState gpio[FSL_IMX8MM_NUM_GPIOS];
IMX8MMCCMState ccm;
IMX8MMAnalogState analog;
IMX7SNVSState snvs;
@@ -169,6 +172,17 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_UART3_IRQ = 28,
FSL_IMX8MM_UART4_IRQ = 29,
+ FSL_IMX8MM_GPIO1_LOW_IRQ = 64,
+ FSL_IMX8MM_GPIO1_HIGH_IRQ = 65,
+ FSL_IMX8MM_GPIO2_LOW_IRQ = 66,
+ FSL_IMX8MM_GPIO2_HIGH_IRQ = 67,
+ FSL_IMX8MM_GPIO3_LOW_IRQ = 68,
+ FSL_IMX8MM_GPIO3_HIGH_IRQ = 69,
+ FSL_IMX8MM_GPIO4_LOW_IRQ = 70,
+ FSL_IMX8MM_GPIO4_HIGH_IRQ = 71,
+ FSL_IMX8MM_GPIO5_LOW_IRQ = 72,
+ FSL_IMX8MM_GPIO5_HIGH_IRQ = 73,
+
FSL_IMX8MM_PCI_INTA_IRQ = 122,
FSL_IMX8MM_PCI_INTB_IRQ = 123,
FSL_IMX8MM_PCI_INTC_IRQ = 124,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 07/13] hw/arm/fsl-imx8mm: Adding support for I2C emulation
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (5 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 06/13] hw/arm/fsl-imx8mm: Add GPIO controllers Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:07 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 08/13] hw/arm/fsl-imx8mm: Adding support for SPI controller Gaurav Sharma
` (6 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
This can be used to test and debug I2C device drivers.
Added I2C interrupts
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 2 ++
hw/arm/fsl-imx8mm.c | 27 +++++++++++++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 8 ++++++++
4 files changed, 38 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index c55d02c1c2..faf90336e0 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -15,6 +15,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 3 USDHC Storage Controllers
* 1 Designware PCI Express Controller
* 5 GPIO Controllers
+ * 6 I2C Controllers
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 6df1478c4f..d442ea0624 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -629,10 +629,12 @@ config FSL_IMX8MP_EVK
config FSL_IMX8MM
bool
imply PCI_DEVICES
+ imply I2C_DEVICES
select ARM_GIC
select FSL_IMX8MM_ANALOG
select FSL_IMX8MM_CCM
select IMX
+ select IMX_I2C
select SDHCI
select PCI_EXPRESS_DESIGNWARE
select PCI_EXPRESS_FSL_IMX8M_PHY
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 222d3bac1c..eaa9a66efc 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -177,6 +177,11 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
+ g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
+ object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
+ }
+
for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
@@ -355,6 +360,27 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, serial_table[i].irq));
}
+ /* I2Cs */
+ for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq;
+ } i2c_table[FSL_IMX8MM_NUM_I2CS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_I2C1].addr, FSL_IMX8MM_I2C1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_I2C2].addr, FSL_IMX8MM_I2C2_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_I2C3].addr, FSL_IMX8MM_I2C3_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_I2C4].addr, FSL_IMX8MM_I2C4_IRQ },
+ };
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
+ qdev_get_gpio_in(gicdev, i2c_table[i].irq));
+ }
+
/* GPIOs */
for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
struct {
@@ -462,6 +488,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_GIC_DIST:
case FSL_IMX8MM_GIC_REDIST:
case FSL_IMX8MM_GPIO1 ... FSL_IMX8MM_GPIO5:
+ case FSL_IMX8MM_I2C1 ... FSL_IMX8MM_I2C4:
case FSL_IMX8MM_PCIE1:
case FSL_IMX8MM_PCIE_PHY1:
case FSL_IMX8MM_RAM:
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index d3a2d1843f..e68dbd188b 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -12,6 +12,7 @@
#include "cpu.h"
#include "hw/char/imx_serial.h"
#include "hw/gpio/imx_gpio.h"
+#include "hw/i2c/imx_i2c.h"
#include "hw/intc/arm_gicv3_common.h"
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
@@ -31,6 +32,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_CPUS = 4,
FSL_IMX8MM_NUM_GPIOS = 5,
+ FSL_IMX8MM_NUM_I2CS = 4,
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
FSL_IMX8MM_NUM_USDHCS = 3,
@@ -45,6 +47,7 @@ struct FslImx8mmState {
IMX8MMCCMState ccm;
IMX8MMAnalogState analog;
IMX7SNVSState snvs;
+ IMXI2CState i2c[FSL_IMX8MM_NUM_I2CS];
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
DesignwarePCIEHost pcie;
@@ -172,6 +175,11 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_UART3_IRQ = 28,
FSL_IMX8MM_UART4_IRQ = 29,
+ FSL_IMX8MM_I2C1_IRQ = 35,
+ FSL_IMX8MM_I2C2_IRQ = 36,
+ FSL_IMX8MM_I2C3_IRQ = 37,
+ FSL_IMX8MM_I2C4_IRQ = 38,
+
FSL_IMX8MM_GPIO1_LOW_IRQ = 64,
FSL_IMX8MM_GPIO1_HIGH_IRQ = 65,
FSL_IMX8MM_GPIO2_LOW_IRQ = 66,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 08/13] hw/arm/fsl-imx8mm: Adding support for SPI controller
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (6 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 07/13] hw/arm/fsl-imx8mm: Adding support for I2C emulation Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:08 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 09/13] hw/arm/fsl-imx8mm: Adding support for Watchdog Timers Gaurav Sharma
` (5 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
It enables emulation of ECSPI in iMX8MM
Added SPI IRQ lines
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/fsl-imx8mm.c | 26 ++++++++++++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 7 +++++++
3 files changed, 34 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index faf90336e0..bbe2d2e6e2 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -16,6 +16,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 1 Designware PCI Express Controller
* 5 GPIO Controllers
* 6 I2C Controllers
+ * 3 SPI Controllers
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index eaa9a66efc..c15d8cf8d6 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -192,6 +192,11 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
+ g_autofree char *name = g_strdup_printf("spi%d", i + 1);
+ object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
+ }
+
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
TYPE_FSL_IMX8M_PCIE_PHY);
@@ -449,6 +454,26 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
}
+ /* ECSPIs */
+ for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq;
+ } spi_table[FSL_IMX8MM_NUM_ECSPIS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI1].addr, FSL_IMX8MM_ECSPI1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI2].addr, FSL_IMX8MM_ECSPI2_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI3].addr, FSL_IMX8MM_ECSPI3_IRQ },
+ };
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
+ qdev_get_gpio_in(gicdev, spi_table[i].irq));
+ }
+
/* SNVS */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
return;
@@ -488,6 +513,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_GIC_DIST:
case FSL_IMX8MM_GIC_REDIST:
case FSL_IMX8MM_GPIO1 ... FSL_IMX8MM_GPIO5:
+ case FSL_IMX8MM_ECSPI1 ... FSL_IMX8MM_ECSPI3:
case FSL_IMX8MM_I2C1 ... FSL_IMX8MM_I2C4:
case FSL_IMX8MM_PCIE1:
case FSL_IMX8MM_PCIE_PHY1:
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index e68dbd188b..f3a3304565 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -20,6 +20,7 @@
#include "hw/pci-host/designware.h"
#include "hw/pci-host/fsl_imx8m_phy.h"
#include "hw/sd/sdhci.h"
+#include "hw/ssi/imx_spi.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -31,6 +32,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_CPUS = 4,
+ FSL_IMX8MM_NUM_ECSPIS = 3,
FSL_IMX8MM_NUM_GPIOS = 5,
FSL_IMX8MM_NUM_I2CS = 4,
FSL_IMX8MM_NUM_IRQS = 128,
@@ -47,6 +49,7 @@ struct FslImx8mmState {
IMX8MMCCMState ccm;
IMX8MMAnalogState analog;
IMX7SNVSState snvs;
+ IMXSPIState spi[FSL_IMX8MM_NUM_ECSPIS];
IMXI2CState i2c[FSL_IMX8MM_NUM_I2CS];
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
@@ -175,6 +178,10 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_UART3_IRQ = 28,
FSL_IMX8MM_UART4_IRQ = 29,
+ FSL_IMX8MM_ECSPI1_IRQ = 31,
+ FSL_IMX8MM_ECSPI2_IRQ = 32,
+ FSL_IMX8MM_ECSPI3_IRQ = 33,
+
FSL_IMX8MM_I2C1_IRQ = 35,
FSL_IMX8MM_I2C2_IRQ = 36,
FSL_IMX8MM_I2C3_IRQ = 37,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 09/13] hw/arm/fsl-imx8mm: Adding support for Watchdog Timers
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (7 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 08/13] hw/arm/fsl-imx8mm: Adding support for SPI controller Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:12 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 10/13] hw/arm/fsl-imx8mm: Adding support for General Purpose Timers Gaurav Sharma
` (4 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
It enables emulation of WDT in iMX8MM
Added WDT IRQ lines
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 1 +
hw/arm/fsl-imx8mm.c | 28 ++++++++++++++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 7 +++++++
4 files changed, 37 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index bbe2d2e6e2..5311e685fb 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -17,6 +17,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 5 GPIO Controllers
* 6 I2C Controllers
* 3 SPI Controllers
+ * 3 Watchdogs
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index d442ea0624..9498a96f30 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -638,6 +638,7 @@ config FSL_IMX8MM
select SDHCI
select PCI_EXPRESS_DESIGNWARE
select PCI_EXPRESS_FSL_IMX8M_PHY
+ select WDT_IMX2
config FSL_IMX8MM_EVK
bool
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index c15d8cf8d6..6ee2890736 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -197,6 +197,11 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_WDTS; i++) {
+ g_autofree char *name = g_strdup_printf("wdt%d", i);
+ object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
+ }
+
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
TYPE_FSL_IMX8M_PCIE_PHY);
@@ -481,6 +486,28 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
fsl_imx8mm_memmap[FSL_IMX8MM_SNVS_HP].addr);
+ /* Watchdogs */
+ for (i = 0; i < FSL_IMX8MM_NUM_WDTS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq;
+ } wdog_table[FSL_IMX8MM_NUM_WDTS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG1].addr, FSL_IMX8MM_WDOG1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG2].addr, FSL_IMX8MM_WDOG2_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG3].addr, FSL_IMX8MM_WDOG3_IRQ },
+ };
+
+ object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
+ true, &error_abort);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
+ qdev_get_gpio_in(gicdev, wdog_table[i].irq));
+ }
+
/* PCIe */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
return;
@@ -521,6 +548,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_SNVS_HP:
case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
case FSL_IMX8MM_USDHC1 ... FSL_IMX8MM_USDHC3:
+ case FSL_IMX8MM_WDOG1 ... FSL_IMX8MM_WDOG3:
/* device implemented and treated above */
break;
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index f3a3304565..7107e932c6 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -21,6 +21,7 @@
#include "hw/pci-host/fsl_imx8m_phy.h"
#include "hw/sd/sdhci.h"
#include "hw/ssi/imx_spi.h"
+#include "hw/watchdog/wdt_imx2.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -38,6 +39,7 @@ enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
FSL_IMX8MM_NUM_USDHCS = 3,
+ FSL_IMX8MM_NUM_WDTS = 3,
};
struct FslImx8mmState {
@@ -53,6 +55,7 @@ struct FslImx8mmState {
IMXI2CState i2c[FSL_IMX8MM_NUM_I2CS];
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
+ IMX2WdtState wdt[FSL_IMX8MM_NUM_WDTS];
DesignwarePCIEHost pcie;
FslImx8mPciePhyState pcie_phy;
};
@@ -198,6 +201,10 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_GPIO5_LOW_IRQ = 72,
FSL_IMX8MM_GPIO5_HIGH_IRQ = 73,
+ FSL_IMX8MM_WDOG1_IRQ = 78,
+ FSL_IMX8MM_WDOG2_IRQ = 79,
+ FSL_IMX8MM_WDOG3_IRQ = 10,
+
FSL_IMX8MM_PCI_INTA_IRQ = 122,
FSL_IMX8MM_PCI_INTB_IRQ = 123,
FSL_IMX8MM_PCI_INTC_IRQ = 124,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 10/13] hw/arm/fsl-imx8mm: Adding support for General Purpose Timers
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (8 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 09/13] hw/arm/fsl-imx8mm: Adding support for Watchdog Timers Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 11:22 ` [PATCH 11/13] hw/arm/fsl-imx8mm: Adding support for ENET ethernet controller Gaurav Sharma
` (3 subsequent siblings)
13 siblings, 0 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
It enables emulation of GPT in iMX8MM
Added GPT IRQ lines
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 1 +
hw/arm/fsl-imx8mm.c | 53 ++++++++++++++++++++++++++++++++++
hw/timer/imx_gpt.c | 26 +++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 11 +++++++
include/hw/timer/imx_gpt.h | 2 ++
6 files changed, 94 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index 5311e685fb..ae2d73a652 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -18,6 +18,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 6 I2C Controllers
* 3 SPI Controllers
* 3 Watchdogs
+ * 6 General Purpose Timers
* Secure Non-Volatile Storage (SNVS) including an RTC
* Clock Tree
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 9498a96f30..733baea384 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -635,6 +635,7 @@ config FSL_IMX8MM
select FSL_IMX8MM_CCM
select IMX
select IMX_I2C
+ select OR_IRQ
select SDHCI
select PCI_EXPRESS_DESIGNWARE
select PCI_EXPRESS_FSL_IMX8M_PHY
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 6ee2890736..497201afa6 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -177,6 +177,13 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_GPTS; i++) {
+ g_autofree char *name = g_strdup_printf("gpt%d", i + 1);
+ object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX8MM_GPT);
+ }
+ object_initialize_child(obj, "gpt5-gpt6-irq", &s->gpt5_gpt6_irq,
+ TYPE_OR_IRQ);
+
for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
@@ -370,6 +377,52 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, serial_table[i].irq));
}
+ /* GPTs */
+ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2,
+ &error_abort);
+ if (!qdev_realize(DEVICE(&s->gpt5_gpt6_irq), NULL, errp)) {
+ return;
+ }
+
+ qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_GPT5_GPT6_IRQ));
+
+ for (i = 0; i < FSL_IMX8MM_NUM_GPTS; i++) {
+ hwaddr gpt_addrs[FSL_IMX8MM_NUM_GPTS] = {
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPT1].addr,
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPT2].addr,
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPT3].addr,
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPT4].addr,
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPT5].addr,
+ fsl_imx8mm_memmap[FSL_IMX8MM_GPT6].addr,
+ };
+
+ s->gpt[i].ccm = IMX_CCM(&s->ccm);
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_addrs[i]);
+
+ if (i < FSL_IMX8MM_NUM_GPTS - 2) {
+ static const unsigned int gpt_irqs[FSL_IMX8MM_NUM_GPTS - 2] = {
+ FSL_IMX8MM_GPT1_IRQ,
+ FSL_IMX8MM_GPT2_IRQ,
+ FSL_IMX8MM_GPT3_IRQ,
+ FSL_IMX8MM_GPT4_IRQ,
+ };
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
+ qdev_get_gpio_in(gicdev, gpt_irqs[i]));
+ } else {
+ int irq = i - FSL_IMX8MM_NUM_GPTS + 2;
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->gpt5_gpt6_irq), irq));
+ }
+ }
+
/* I2Cs */
for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
struct {
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 8c7cbfdeac..5eba637f7d 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -6,6 +6,7 @@
* Originally written by Hans Jiang
* Updated by Peter Chubb
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ * Updated by Gaurav Sharma <gaurav.sharma_7@nxp.com>
*
* This code is licensed under GPL version 2 or later. See
* the COPYING file in the top-level directory.
@@ -137,6 +138,17 @@ static const IMXClk imx8mp_gpt_clocks[] = {
CLK_NONE, /* 111 not defined */
};
+static const IMXClk imx8mm_gpt_clocks[] = {
+ CLK_NONE, /* 000 No clock source */
+ CLK_IPG, /* 001 ipg_clk, 532MHz */
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
+ CLK_EXT, /* 011 External clock */
+ CLK_32k, /* 100 ipg_clk_32k */
+ CLK_HIGH, /* 101 ipg_clk_16M */
+ CLK_NONE, /* 110 not defined */
+ CLK_NONE, /* 111 not defined */
+};
+
/* Must be called from within ptimer_transaction_begin/commit block */
static void imx_gpt_set_freq(IMXGPTState *s)
{
@@ -570,6 +582,13 @@ static void imx8mp_gpt_init(Object *obj)
s->clocks = imx8mp_gpt_clocks;
}
+static void imx8mm_gpt_init(Object *obj)
+{
+ IMXGPTState *s = IMX_GPT(obj);
+
+ s->clocks = imx8mm_gpt_clocks;
+}
+
static const TypeInfo imx25_gpt_info = {
.name = TYPE_IMX25_GPT,
.parent = TYPE_SYS_BUS_DEVICE,
@@ -608,6 +627,12 @@ static const TypeInfo imx8mp_gpt_info = {
.instance_init = imx8mp_gpt_init,
};
+static const TypeInfo imx8mm_gpt_info = {
+ .name = TYPE_IMX8MM_GPT,
+ .parent = TYPE_IMX25_GPT,
+ .instance_init = imx8mm_gpt_init,
+};
+
static void imx_gpt_register_types(void)
{
type_register_static(&imx25_gpt_info);
@@ -616,6 +641,7 @@ static void imx_gpt_register_types(void)
type_register_static(&imx6ul_gpt_info);
type_register_static(&imx7_gpt_info);
type_register_static(&imx8mp_gpt_info);
+ type_register_static(&imx8mm_gpt_info);
}
type_init(imx_gpt_register_types)
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 7107e932c6..6b70be81d2 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -17,10 +17,12 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
#include "hw/misc/imx8mm_ccm.h"
+#include "hw/or-irq.h"
#include "hw/pci-host/designware.h"
#include "hw/pci-host/fsl_imx8m_phy.h"
#include "hw/sd/sdhci.h"
#include "hw/ssi/imx_spi.h"
+#include "hw/timer/imx_gpt.h"
#include "hw/watchdog/wdt_imx2.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -35,6 +37,7 @@ enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_CPUS = 4,
FSL_IMX8MM_NUM_ECSPIS = 3,
FSL_IMX8MM_NUM_GPIOS = 5,
+ FSL_IMX8MM_NUM_GPTS = 6,
FSL_IMX8MM_NUM_I2CS = 4,
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
@@ -47,6 +50,7 @@ struct FslImx8mmState {
ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
GICv3State gic;
+ IMXGPTState gpt[FSL_IMX8MM_NUM_GPTS];
IMXGPIOState gpio[FSL_IMX8MM_NUM_GPIOS];
IMX8MMCCMState ccm;
IMX8MMAnalogState analog;
@@ -58,6 +62,7 @@ struct FslImx8mmState {
IMX2WdtState wdt[FSL_IMX8MM_NUM_WDTS];
DesignwarePCIEHost pcie;
FslImx8mPciePhyState pcie_phy;
+ OrIRQState gpt5_gpt6_irq;
};
enum FslImx8mmMemoryRegions {
@@ -190,6 +195,12 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_I2C3_IRQ = 37,
FSL_IMX8MM_I2C4_IRQ = 38,
+ FSL_IMX8MM_GPT1_IRQ = 55,
+ FSL_IMX8MM_GPT2_IRQ = 54,
+ FSL_IMX8MM_GPT3_IRQ = 53,
+ FSL_IMX8MM_GPT4_IRQ = 52,
+ FSL_IMX8MM_GPT5_GPT6_IRQ = 51,
+
FSL_IMX8MM_GPIO1_LOW_IRQ = 64,
FSL_IMX8MM_GPIO1_HIGH_IRQ = 65,
FSL_IMX8MM_GPIO2_LOW_IRQ = 66,
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
index 5488f7e4df..379ee5de75 100644
--- a/include/hw/timer/imx_gpt.h
+++ b/include/hw/timer/imx_gpt.h
@@ -6,6 +6,7 @@
* Originally written by Hans Jiang
* Updated by Peter Chubb
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ * Updated by Gaurav Sharma <gaurav.sharma_7@nxp.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -81,6 +82,7 @@
#define TYPE_IMX6UL_GPT "imx6ul.gpt"
#define TYPE_IMX7_GPT "imx7.gpt"
#define TYPE_IMX8MP_GPT "imx8mp.gpt"
+#define TYPE_IMX8MM_GPT "imx8mm.gpt"
#define TYPE_IMX_GPT TYPE_IMX25_GPT
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 11/13] hw/arm/fsl-imx8mm: Adding support for ENET ethernet controller
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (9 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 10/13] hw/arm/fsl-imx8mm: Adding support for General Purpose Timers Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 11:22 ` [PATCH 12/13] hw/arm/fsl-imx8mm: Adding support for USB controller Gaurav Sharma
` (2 subsequent siblings)
13 siblings, 0 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
It enables emulation of ENET ethernet controller in iMX8MM
Enables testing and debugging of network dependent drivers
Added ENET MAC IRQ lines
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 1 +
hw/arm/fsl-imx8mm.c | 24 ++++++++++++++++++++++++
hw/arm/imx8mm-evk.c | 1 +
include/hw/arm/fsl-imx8mm.h | 8 ++++++++
5 files changed, 35 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index ae2d73a652..14aaff2004 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -14,6 +14,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 4 UARTs
* 3 USDHC Storage Controllers
* 1 Designware PCI Express Controller
+ * 1 Ethernet Controller
* 5 GPIO Controllers
* 6 I2C Controllers
* 3 SPI Controllers
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 733baea384..d41d03d728 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -634,6 +634,7 @@ config FSL_IMX8MM
select FSL_IMX8MM_ANALOG
select FSL_IMX8MM_CCM
select IMX
+ select IMX_FEC
select IMX_I2C
select OR_IRQ
select SDHCI
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 497201afa6..6ae388ebdd 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -209,6 +209,8 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
}
+ object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
+
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
TYPE_FSL_IMX8M_PCIE_PHY);
@@ -532,6 +534,21 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, spi_table[i].irq));
}
+ /* ENET1 */
+ object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
+ &error_abort);
+ object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
+ qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
+ fsl_imx8mm_memmap[FSL_IMX8MM_ENET1].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
+ qdev_get_gpio_in(gicdev, FSL_IMX8MM_ENET1_MAC_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
+ qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
+
/* SNVS */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
return;
@@ -594,6 +611,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_GIC_REDIST:
case FSL_IMX8MM_GPIO1 ... FSL_IMX8MM_GPIO5:
case FSL_IMX8MM_ECSPI1 ... FSL_IMX8MM_ECSPI3:
+ case FSL_IMX8MM_ENET1:
case FSL_IMX8MM_I2C1 ... FSL_IMX8MM_I2C4:
case FSL_IMX8MM_PCIE1:
case FSL_IMX8MM_PCIE_PHY1:
@@ -614,10 +632,16 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
}
}
+static const Property fsl_imx8mm_properties[] = {
+ DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mmState, phy_num, 0),
+ DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mmState, phy_connected, true),
+};
+
static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ device_class_set_props(dc, fsl_imx8mm_properties);
dc->realize = fsl_imx8mm_realize;
dc->desc = "i.MX 8MM SoC";
diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c
index a4ab910ee4..6595478a46 100644
--- a/hw/arm/imx8mm-evk.c
+++ b/hw/arm/imx8mm-evk.c
@@ -75,6 +75,7 @@ static void imx8mm_evk_init(MachineState *machine)
};
s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
+ object_property_set_uint(OBJECT(s), "fec1-phy-num", 1, &error_fatal);
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal);
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 6b70be81d2..356627ab82 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -17,6 +17,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mm_analog.h"
#include "hw/misc/imx8mm_ccm.h"
+#include "hw/net/imx_fec.h"
#include "hw/or-irq.h"
#include "hw/pci-host/designware.h"
#include "hw/pci-host/fsl_imx8m_phy.h"
@@ -58,11 +59,15 @@ struct FslImx8mmState {
IMXSPIState spi[FSL_IMX8MM_NUM_ECSPIS];
IMXI2CState i2c[FSL_IMX8MM_NUM_I2CS];
IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
+ IMXFECState enet;
SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
IMX2WdtState wdt[FSL_IMX8MM_NUM_WDTS];
DesignwarePCIEHost pcie;
FslImx8mPciePhyState pcie_phy;
OrIRQState gpt5_gpt6_irq;
+
+ uint32_t phy_num;
+ bool phy_connected;
};
enum FslImx8mmMemoryRegions {
@@ -216,6 +221,9 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_WDOG2_IRQ = 79,
FSL_IMX8MM_WDOG3_IRQ = 10,
+ FSL_IMX8MM_ENET1_MAC_IRQ = 118,
+ FSL_IMX6_ENET1_MAC_1588_IRQ = 121,
+
FSL_IMX8MM_PCI_INTA_IRQ = 122,
FSL_IMX8MM_PCI_INTB_IRQ = 123,
FSL_IMX8MM_PCI_INTC_IRQ = 124,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 12/13] hw/arm/fsl-imx8mm: Adding support for USB controller
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (10 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 11/13] hw/arm/fsl-imx8mm: Adding support for ENET ethernet controller Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-10 15:10 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation Gaurav Sharma
2025-11-10 14:38 ` [PATCH v2 00/13] Adding comprehensive support for i.MX8MM EVK board Philippe Mathieu-Daudé
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
It enables emulation of USB on iMX8MM
Enables testing and debugging of USB drivers
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
docs/system/arm/imx8mm-evk.rst | 1 +
hw/arm/Kconfig | 1 +
hw/arm/fsl-imx8mm.c | 27 +++++++++++++++++++++++++++
include/hw/arm/fsl-imx8mm.h | 6 ++++++
4 files changed, 35 insertions(+)
diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
index 14aaff2004..15020a4182 100644
--- a/docs/system/arm/imx8mm-evk.rst
+++ b/docs/system/arm/imx8mm-evk.rst
@@ -15,6 +15,7 @@ The ``imx8mm-evk`` machine implements the following devices:
* 3 USDHC Storage Controllers
* 1 Designware PCI Express Controller
* 1 Ethernet Controller
+ * 2 Designware USB 3 Controllers
* 5 GPIO Controllers
* 6 I2C Controllers
* 3 SPI Controllers
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index d41d03d728..39c63a3aea 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -640,6 +640,7 @@ config FSL_IMX8MM
select SDHCI
select PCI_EXPRESS_DESIGNWARE
select PCI_EXPRESS_FSL_IMX8M_PHY
+ select USB_DWC3
select WDT_IMX2
config FSL_IMX8MM_EVK
diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
index 6ae388ebdd..d522abfb67 100644
--- a/hw/arm/fsl-imx8mm.c
+++ b/hw/arm/fsl-imx8mm.c
@@ -199,6 +199,11 @@ static void fsl_imx8mm_init(Object *obj)
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
}
+ for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
+ g_autofree char *name = g_strdup_printf("usb%d", i);
+ object_initialize_child(obj, name, &s->usb[i], TYPE_USB_DWC3);
+ }
+
for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
g_autofree char *name = g_strdup_printf("spi%d", i + 1);
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
@@ -514,6 +519,27 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
}
+ /* USBs */
+ for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
+ struct {
+ hwaddr addr;
+ unsigned int irq;
+ } usb_table[FSL_IMX8MM_NUM_USBS] = {
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USB1].addr, FSL_IMX8MM_USB1_IRQ },
+ { fsl_imx8mm_memmap[FSL_IMX8MM_USB2].addr, FSL_IMX8MM_USB2_IRQ },
+ };
+
+ qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p2", 1);
+ qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p3", 1);
+ qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) {
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
+ qdev_get_gpio_in(gicdev, usb_table[i].irq));
+ }
+
/* ECSPIs */
for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
struct {
@@ -618,6 +644,7 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
case FSL_IMX8MM_RAM:
case FSL_IMX8MM_SNVS_HP:
case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
+ case FSL_IMX8MM_USB1 ... FSL_IMX8MM_USB2:
case FSL_IMX8MM_USDHC1 ... FSL_IMX8MM_USDHC3:
case FSL_IMX8MM_WDOG1 ... FSL_IMX8MM_WDOG3:
/* device implemented and treated above */
diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
index 356627ab82..6a0b911acf 100644
--- a/include/hw/arm/fsl-imx8mm.h
+++ b/include/hw/arm/fsl-imx8mm.h
@@ -24,6 +24,7 @@
#include "hw/sd/sdhci.h"
#include "hw/ssi/imx_spi.h"
#include "hw/timer/imx_gpt.h"
+#include "hw/usb/hcd-dwc3.h"
#include "hw/watchdog/wdt_imx2.h"
#include "qom/object.h"
#include "qemu/units.h"
@@ -42,6 +43,7 @@ enum FslImx8mmConfiguration {
FSL_IMX8MM_NUM_I2CS = 4,
FSL_IMX8MM_NUM_IRQS = 128,
FSL_IMX8MM_NUM_UARTS = 4,
+ FSL_IMX8MM_NUM_USBS = 2,
FSL_IMX8MM_NUM_USDHCS = 3,
FSL_IMX8MM_NUM_WDTS = 3,
};
@@ -62,6 +64,7 @@ struct FslImx8mmState {
IMXFECState enet;
SDHCIState usdhc[FSL_IMX8MM_NUM_USDHCS];
IMX2WdtState wdt[FSL_IMX8MM_NUM_WDTS];
+ USBDWC3 usb[FSL_IMX8MM_NUM_USBS];
DesignwarePCIEHost pcie;
FslImx8mPciePhyState pcie_phy;
OrIRQState gpt5_gpt6_irq;
@@ -200,6 +203,9 @@ enum FslImx8mmIrqs {
FSL_IMX8MM_I2C3_IRQ = 37,
FSL_IMX8MM_I2C4_IRQ = 38,
+ FSL_IMX8MM_USB1_IRQ = 40,
+ FSL_IMX8MM_USB2_IRQ = 41,
+
FSL_IMX8MM_GPT1_IRQ = 55,
FSL_IMX8MM_GPT2_IRQ = 54,
FSL_IMX8MM_GPT3_IRQ = 53,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (11 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 12/13] hw/arm/fsl-imx8mm: Adding support for USB controller Gaurav Sharma
@ 2025-11-10 11:22 ` Gaurav Sharma
2025-11-11 23:21 ` Bernhard Beschow
2025-11-10 14:38 ` [PATCH v2 00/13] Adding comprehensive support for i.MX8MM EVK board Philippe Mathieu-Daudé
13 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-10 11:22 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, peter.maydell, Gaurav Sharma
Added script that would validate the iMX8MM emulation by checking the
linux console log. If it succeeds, it will return:-
ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
---
tests/functional/aarch64/meson.build | 2 +
tests/functional/aarch64/test_imx8mm_evk.py | 67 +++++++++++++++++++++
2 files changed, 69 insertions(+)
create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
diff --git a/tests/functional/aarch64/meson.build b/tests/functional/aarch64/meson.build
index 5ad52f93e1..31ecedbf6f 100644
--- a/tests/functional/aarch64/meson.build
+++ b/tests/functional/aarch64/meson.build
@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
'aspeed_ast2700fc' : 600,
'device_passthrough' : 720,
'imx8mp_evk' : 240,
+ 'imx8mm_evk' : 240,
'raspi4' : 480,
'reverse_debug' : 180,
'rme_virt' : 1200,
@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
'device_passthrough',
'hotplug_pci',
'imx8mp_evk',
+ 'imx8mm_evk',
'kvm',
'multiprocess',
'raspi3',
diff --git a/tests/functional/aarch64/test_imx8mm_evk.py b/tests/functional/aarch64/test_imx8mm_evk.py
new file mode 100755
index 0000000000..d5eb43afc6
--- /dev/null
+++ b/tests/functional/aarch64/test_imx8mm_evk.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+class Imx8mmEvkMachine(LinuxKernelTest):
+
+ ASSET_IMAGE = Asset(
+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
+
+ KERNEL_OFFSET = 0x51000000
+ KERNEL_SIZE = 32622528
+ INITRD_OFFSET = 0x76000000
+ INITRD_SIZE = 30987766
+ DTB_OFFSET = 0x64F51000
+ DTB_SIZE = 45 * 1024
+
+ def extract(self, in_path, out_path, offset, size):
+ try:
+ with open(in_path, "rb") as source:
+ source.seek(offset)
+ data = source.read(size)
+ with open(out_path, "wb") as target:
+ target.write(data)
+ except (IOError, ValueError) as e:
+ self.log.error(f"Failed to extract {out_path}: {e}")
+ raise
+
+ def setUp(self):
+ super().setUp()
+
+ self.image_path = self.scratch_file("disk.raw")
+ self.kernel_path = self.scratch_file("linux")
+ self.initrd_path = self.scratch_file("initrd.zstd")
+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
+
+ self.archive_extract(self.ASSET_IMAGE)
+ self.extract(self.image_path, self.kernel_path,
+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
+ self.extract(self.image_path, self.initrd_path,
+ self.INITRD_OFFSET, self.INITRD_SIZE)
+ self.extract(self.image_path, self.dtb_path,
+ self.DTB_OFFSET, self.DTB_SIZE)
+
+ def test_aarch64_imx8mm_evk_usdhc(self):
+ self.require_accelerator("tcg")
+ self.set_machine('imx8mm-evk')
+ self.vm.set_console(console_index=1)
+ self.vm.add_args('-m', '2G',
+ '-smp', '4',
+ '-kernel', self.kernel_path,
+ '-initrd', self.initrd_path,
+ '-dtb', self.dtb_path,
+ '-append', 'root=/dev/mmcblk2p1',
+ '-drive', f'file={self.image_path},if=sd,bus=2,'
+ 'format=raw,id=mmcblk2,snapshot=on')
+
+ self.vm.launch()
+ self.wait_for_console_pattern('Welcome to ')
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH v2 00/13] Adding comprehensive support for i.MX8MM EVK board
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
` (12 preceding siblings ...)
2025-11-10 11:22 ` [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation Gaurav Sharma
@ 2025-11-10 14:38 ` Philippe Mathieu-Daudé
13 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 14:38 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
Hi Gaurav,
On 10/11/25 12:22, Gaurav Sharma wrote:
> This patch series adds support for the NXP i.MX8MM EVK (Evaluation Kit)
> board to QEMU, enabling emulation of this ARM Cortex-A53 based development
> platform.
>
> The series includes:
>
> 1. Core peripheral support (CCM clock controller, Analog module)
> 2. GPT(General Purpose Timer) and WDT(Watchdog Timer) Emulation support
> 3. GPIO,I2C,SPI,USDHC and USB Emulation support
> 4. PCIe and ENET Controller Emulation support
> 5. Documentation and functional test included
>
> Key features ported:
> - Basic boot support with Linux
> - UART console for serial communication
> - Interrupt handling
> - Clock and power management infrastructure
>
> Testing:
> - Linux kernel boots to console
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>
> Gaurav Sharma (13):
> hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
> hw/arm/fsl-imx8mm: Implemented CCM(Clock Control Module) and Analog IP
> hw/arm/fsl-imx8mm: Implemented support for SNVS
> hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers
> hw/arm/fsl-imx8mm: Add PCIe support
> hw/arm/fsl-imx8mm: Add GPIO controllers
> hw/arm/fsl-imx8mm: Adding support for I2C emulation
> hw/arm/fsl-imx8mm: Adding support for SPI controller
> hw/arm/fsl-imx8mm: Adding support for Watchdog Timers
> hw/arm/fsl-imx8mm: Adding support for General Purpose Timers
> hw/arm/fsl-imx8mm: Adding support for ENET ethernet controller
> hw/arm/fsl-imx8mm: Adding support for USB controller
> hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
Thanks a lot for splitting the previous patch so cleanly,
review will be much easier. Also kudo for including a functional
test :)
Regards,
Phil.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 05/13] hw/arm/fsl-imx8mm: Add PCIe support
2025-11-10 11:22 ` [PATCH 05/13] hw/arm/fsl-imx8mm: Add PCIe support Gaurav Sharma
@ 2025-11-10 15:00 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:00 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> This enables support for Designware PCI Express Controller emulation
> It provides a controlled environment to debug the linux pci subsystem
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/Kconfig | 3 +++
> hw/arm/fsl-imx8mm.c | 30 ++++++++++++++++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 10 ++++++++++
> 4 files changed, 44 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 06/13] hw/arm/fsl-imx8mm: Add GPIO controllers
2025-11-10 11:22 ` [PATCH 06/13] hw/arm/fsl-imx8mm: Add GPIO controllers Gaurav Sharma
@ 2025-11-10 15:02 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:02 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> Enabled GPIO controller emulation
> Also updated the GPIO IRQ lines of iMX8MM
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/fsl-imx8mm.c | 54 ++++++++++++++++++++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 14 +++++++++
> 3 files changed, 69 insertions(+)
> diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
> index ea5799b2cc..222d3bac1c 100644
> --- a/hw/arm/fsl-imx8mm.c
> +++ b/hw/arm/fsl-imx8mm.c
> @@ -177,6 +177,11 @@ static void fsl_imx8mm_init(Object *obj)
> object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
> }
>
> + for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
> + g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
> + object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
> + }
> +
> for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
> g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
> object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
> @@ -350,6 +355,54 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> qdev_get_gpio_in(gicdev, serial_table[i].irq));
> }
>
> + /* GPIOs */
> + for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq_low;
> + unsigned int irq_high;
> + } gpio_table[FSL_IMX8MM_NUM_GPIOS] = {
> + {
> + fsl_imx8mm_memmap[FSL_IMX8MM_GPIO1].addr,
> + FSL_IMX8MM_GPIO1_LOW_IRQ,
> + FSL_IMX8MM_GPIO1_HIGH_IRQ
> + },
> + {
> + fsl_imx8mm_memmap[FSL_IMX8MM_GPIO2].addr,
> + FSL_IMX8MM_GPIO2_LOW_IRQ,
> + FSL_IMX8MM_GPIO2_HIGH_IRQ
> + },
> + {
> + fsl_imx8mm_memmap[FSL_IMX8MM_GPIO3].addr,
> + FSL_IMX8MM_GPIO3_LOW_IRQ,
> + FSL_IMX8MM_GPIO3_HIGH_IRQ
> + },
> + {
> + fsl_imx8mm_memmap[FSL_IMX8MM_GPIO4].addr,
> + FSL_IMX8MM_GPIO4_LOW_IRQ,
> + FSL_IMX8MM_GPIO4_HIGH_IRQ
> + },
> + {
> + fsl_imx8mm_memmap[FSL_IMX8MM_GPIO5].addr,
> + FSL_IMX8MM_GPIO5_LOW_IRQ,
> + FSL_IMX8MM_GPIO5_HIGH_IRQ
> + },
> + };
> + object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
> + &error_abort);
> + object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq",
> + true, &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
> + return;
> + }
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
> + qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
> + qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers
2025-11-10 11:22 ` [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers Gaurav Sharma
@ 2025-11-10 15:05 ` Philippe Mathieu-Daudé
2025-11-11 6:09 ` [EXT] " Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:05 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> It enables emulation of SD/MMC cards through a virtual SDHCI interface
> The emulated SDHCI controller allows guest OS to use emulated storage as
> a standard block device.
> This will allow running the images such as those generated
> by Buildroot.
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/Kconfig | 1 +
> hw/arm/fsl-imx8mm.c | 25 +++++++++++++++++++++++++
> hw/arm/imx8mm-evk.c | 17 +++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 7 +++++++
> 5 files changed, 51 insertions(+)
> @@ -342,6 +346,26 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> qdev_get_gpio_in(gicdev, serial_table[i].irq));
> }
>
> + /* USDHCs */
> + for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq;
> + } usdhc_table[FSL_IMX8MM_NUM_USDHCS] = {
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC1].addr, FSL_IMX8MM_USDHC1_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC2].addr, FSL_IMX8MM_USDHC2_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC3].addr, FSL_IMX8MM_USDHC3_IRQ },
> + };
> +
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
> + return;
> + }
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
> + qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 07/13] hw/arm/fsl-imx8mm: Adding support for I2C emulation
2025-11-10 11:22 ` [PATCH 07/13] hw/arm/fsl-imx8mm: Adding support for I2C emulation Gaurav Sharma
@ 2025-11-10 15:07 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:07 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> This can be used to test and debug I2C device drivers.
> Added I2C interrupts
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/Kconfig | 2 ++
> hw/arm/fsl-imx8mm.c | 27 +++++++++++++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 8 ++++++++
> 4 files changed, 38 insertions(+)
> diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
> index 222d3bac1c..eaa9a66efc 100644
> --- a/hw/arm/fsl-imx8mm.c
> +++ b/hw/arm/fsl-imx8mm.c
> @@ -177,6 +177,11 @@ static void fsl_imx8mm_init(Object *obj)
> object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
> }
>
> + for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
> + g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
> + object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
> + }
> +
> for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
> g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
> object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
> @@ -355,6 +360,27 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> qdev_get_gpio_in(gicdev, serial_table[i].irq));
> }
>
> + /* I2Cs */
> + for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq;
> + } i2c_table[FSL_IMX8MM_NUM_I2CS] = {
> + { fsl_imx8mm_memmap[FSL_IMX8MM_I2C1].addr, FSL_IMX8MM_I2C1_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_I2C2].addr, FSL_IMX8MM_I2C2_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_I2C3].addr, FSL_IMX8MM_I2C3_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_I2C4].addr, FSL_IMX8MM_I2C4_IRQ },
> + };
> +
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
> + return;
> + }
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
> + qdev_get_gpio_in(gicdev, i2c_table[i].irq));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 08/13] hw/arm/fsl-imx8mm: Adding support for SPI controller
2025-11-10 11:22 ` [PATCH 08/13] hw/arm/fsl-imx8mm: Adding support for SPI controller Gaurav Sharma
@ 2025-11-10 15:08 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:08 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> It enables emulation of ECSPI in iMX8MM
> Added SPI IRQ lines
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/fsl-imx8mm.c | 26 ++++++++++++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 7 +++++++
> 3 files changed, 34 insertions(+)
> @@ -449,6 +454,26 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
> }
>
> + /* ECSPIs */
> + for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq;
> + } spi_table[FSL_IMX8MM_NUM_ECSPIS] = {
> + { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI1].addr, FSL_IMX8MM_ECSPI1_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI2].addr, FSL_IMX8MM_ECSPI2_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI3].addr, FSL_IMX8MM_ECSPI3_IRQ },
> + };
> +
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
> + return;
> + }
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
> + qdev_get_gpio_in(gicdev, spi_table[i].irq));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 12/13] hw/arm/fsl-imx8mm: Adding support for USB controller
2025-11-10 11:22 ` [PATCH 12/13] hw/arm/fsl-imx8mm: Adding support for USB controller Gaurav Sharma
@ 2025-11-10 15:10 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:10 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> It enables emulation of USB on iMX8MM
> Enables testing and debugging of USB drivers
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/Kconfig | 1 +
> hw/arm/fsl-imx8mm.c | 27 +++++++++++++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 6 ++++++
> 4 files changed, 35 insertions(+)
> @@ -514,6 +519,27 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
> }
>
> + /* USBs */
> + for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq;
> + } usb_table[FSL_IMX8MM_NUM_USBS] = {
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USB1].addr, FSL_IMX8MM_USB1_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USB2].addr, FSL_IMX8MM_USB2_IRQ },
> + };
> +
> + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p2", 1);
> + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p3", 1);
> + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) {
> + return;
> + }
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
> + qdev_get_gpio_in(gicdev, usb_table[i].irq));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 09/13] hw/arm/fsl-imx8mm: Adding support for Watchdog Timers
2025-11-10 11:22 ` [PATCH 09/13] hw/arm/fsl-imx8mm: Adding support for Watchdog Timers Gaurav Sharma
@ 2025-11-10 15:12 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 34+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-10 15:12 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel; +Cc: pbonzini, peter.maydell
On 10/11/25 12:22, Gaurav Sharma wrote:
> It enables emulation of WDT in iMX8MM
> Added WDT IRQ lines
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/Kconfig | 1 +
> hw/arm/fsl-imx8mm.c | 28 ++++++++++++++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 7 +++++++
> 4 files changed, 37 insertions(+)
> @@ -481,6 +486,28 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
> fsl_imx8mm_memmap[FSL_IMX8MM_SNVS_HP].addr);
>
> + /* Watchdogs */
> + for (i = 0; i < FSL_IMX8MM_NUM_WDTS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq;
> + } wdog_table[FSL_IMX8MM_NUM_WDTS] = {
> + { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG1].addr, FSL_IMX8MM_WDOG1_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG2].addr, FSL_IMX8MM_WDOG2_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG3].addr, FSL_IMX8MM_WDOG3_IRQ },
> + };
> +
> + object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
> + true, &error_abort);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
> + return;
> + }
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
> + qdev_get_gpio_in(gicdev, wdog_table[i].irq));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers
2025-11-10 15:05 ` Philippe Mathieu-Daudé
@ 2025-11-11 6:09 ` Gaurav Sharma
0 siblings, 0 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-11 6:09 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Thanks Philippe for reviewing and catching this. Yes, it should be a 'static const' since we do not expect this struct to be modified. My bad. This pattern needs to be fixed in multiple patches. I will wait for additional review comments on the patch series before rolling out a v2. v2 will also have changes to remove iMX8MM CSI and DSI dtb nodes since they are unimplemented.
-----Original Message-----
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Sent: 10 November 2025 20:35
To: Gaurav Sharma <gaurav.sharma_7@nxp.com>; qemu-devel@nongnu.org
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: [EXT] Re: [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers
[You don't often get email from philmd@linaro.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
On 10/11/25 12:22, Gaurav Sharma wrote:
> It enables emulation of SD/MMC cards through a virtual SDHCI interface
> The emulated SDHCI controller allows guest OS to use emulated storage
> as a standard block device.
> This will allow running the images such as those generated by
> Buildroot.
>
> Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
> ---
> docs/system/arm/imx8mm-evk.rst | 1 +
> hw/arm/Kconfig | 1 +
> hw/arm/fsl-imx8mm.c | 25 +++++++++++++++++++++++++
> hw/arm/imx8mm-evk.c | 17 +++++++++++++++++
> include/hw/arm/fsl-imx8mm.h | 7 +++++++
> 5 files changed, 51 insertions(+)
> @@ -342,6 +346,26 @@ static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
> qdev_get_gpio_in(gicdev, serial_table[i].irq));
> }
>
> + /* USDHCs */
> + for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
static const?
> + struct {
> + hwaddr addr;
> + unsigned int irq;
> + } usdhc_table[FSL_IMX8MM_NUM_USDHCS] = {
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC1].addr, FSL_IMX8MM_USDHC1_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC2].addr, FSL_IMX8MM_USDHC2_IRQ },
> + { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC3].addr, FSL_IMX8MM_USDHC3_IRQ },
> + };
> +
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
> + return;
> + }
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
> + qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
> + }
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-10 11:22 ` [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation Gaurav Sharma
@ 2025-11-11 23:21 ` Bernhard Beschow
2025-11-12 6:58 ` [EXT] " Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Bernhard Beschow @ 2025-11-11 23:21 UTC (permalink / raw)
To: qemu-devel, Gaurav Sharma; +Cc: pbonzini, peter.maydell
Am 10. November 2025 11:22:57 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>Added script that would validate the iMX8MM emulation by checking the
>linux console log. If it succeeds, it will return:-
>
>ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
>
>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
Hi Gaurav!
Nice to see another imx8 machine being contributed! I'm impressed how close you stick to the imx8mp, both in terms of structuring this series as well as the code.
I've built your series and ran the functional test. Comments below.
>---
> tests/functional/aarch64/meson.build | 2 +
> tests/functional/aarch64/test_imx8mm_evk.py | 67 +++++++++++++++++++++
> 2 files changed, 69 insertions(+)
> create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
>
>diff --git a/tests/functional/aarch64/meson.build b/tests/functional/aarch64/meson.build
>index 5ad52f93e1..31ecedbf6f 100644
>--- a/tests/functional/aarch64/meson.build
>+++ b/tests/functional/aarch64/meson.build
>@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
> 'aspeed_ast2700fc' : 600,
> 'device_passthrough' : 720,
> 'imx8mp_evk' : 240,
>+ 'imx8mm_evk' : 240,
> 'raspi4' : 480,
> 'reverse_debug' : 180,
> 'rme_virt' : 1200,
>@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
> 'device_passthrough',
> 'hotplug_pci',
> 'imx8mp_evk',
>+ 'imx8mm_evk',
Looks like these lists are sorted alphabetically. Shall we preserve that?
> 'kvm',
> 'multiprocess',
> 'raspi3',
>diff --git a/tests/functional/aarch64/test_imx8mm_evk.py b/tests/functional/aarch64/test_imx8mm_evk.py
>new file mode 100755
>index 0000000000..d5eb43afc6
>--- /dev/null
>+++ b/tests/functional/aarch64/test_imx8mm_evk.py
>@@ -0,0 +1,67 @@
>+#!/usr/bin/env python3
>+#
>+# Functional test that boots a Linux kernel and checks the console
>+#
>+# SPDX-License-Identifier: GPL-2.0-or-later
>+
>+from qemu_test import LinuxKernelTest, Asset
>+
>+class Imx8mmEvkMachine(LinuxKernelTest):
>+
>+ ASSET_IMAGE = Asset(
>+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
>+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
>+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
>+
>+ KERNEL_OFFSET = 0x51000000
>+ KERNEL_SIZE = 32622528
>+ INITRD_OFFSET = 0x76000000
>+ INITRD_SIZE = 30987766
>+ DTB_OFFSET = 0x64F51000
This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway.
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
Best regards,
Bernhard
>+ DTB_SIZE = 45 * 1024
>+
>+ def extract(self, in_path, out_path, offset, size):
>+ try:
>+ with open(in_path, "rb") as source:
>+ source.seek(offset)
>+ data = source.read(size)
>+ with open(out_path, "wb") as target:
>+ target.write(data)
>+ except (IOError, ValueError) as e:
>+ self.log.error(f"Failed to extract {out_path}: {e}")
>+ raise
>+
>+ def setUp(self):
>+ super().setUp()
>+
>+ self.image_path = self.scratch_file("disk.raw")
>+ self.kernel_path = self.scratch_file("linux")
>+ self.initrd_path = self.scratch_file("initrd.zstd")
>+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
>+
>+ self.archive_extract(self.ASSET_IMAGE)
>+ self.extract(self.image_path, self.kernel_path,
>+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
>+ self.extract(self.image_path, self.initrd_path,
>+ self.INITRD_OFFSET, self.INITRD_SIZE)
>+ self.extract(self.image_path, self.dtb_path,
>+ self.DTB_OFFSET, self.DTB_SIZE)
>+
>+ def test_aarch64_imx8mm_evk_usdhc(self):
>+ self.require_accelerator("tcg")
>+ self.set_machine('imx8mm-evk')
>+ self.vm.set_console(console_index=1)
>+ self.vm.add_args('-m', '2G',
>+ '-smp', '4',
>+ '-kernel', self.kernel_path,
>+ '-initrd', self.initrd_path,
>+ '-dtb', self.dtb_path,
>+ '-append', 'root=/dev/mmcblk2p1',
>+ '-drive', f'file={self.image_path},if=sd,bus=2,'
>+ 'format=raw,id=mmcblk2,snapshot=on')
>+
>+ self.vm.launch()
>+ self.wait_for_console_pattern('Welcome to ')
>+
>+if __name__ == '__main__':
>+ LinuxKernelTest.main()
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
2025-11-10 11:22 ` [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board Gaurav Sharma
@ 2025-11-11 23:44 ` Bernhard Beschow
2025-11-13 10:52 ` [EXT] " Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Bernhard Beschow @ 2025-11-11 23:44 UTC (permalink / raw)
To: qemu-devel, Gaurav Sharma; +Cc: pbonzini, peter.maydell
Am 10. November 2025 11:22:45 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>Implemented CPUs, RAM, UARTs and Interrupt Controller
>Other peripherals are represented as TYPE_UNIMPLEMENTED_DEVICE
>Complete memory map of the SoC is provided.
>
>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>---
> docs/system/arm/imx8mm-evk.rst | 70 +++++++
> docs/system/target-arm.rst | 1 +
> hw/arm/Kconfig | 12 ++
> hw/arm/fsl-imx8mm.c | 363 +++++++++++++++++++++++++++++++++
> hw/arm/imx8mm-evk.c | 107 ++++++++++
> hw/arm/meson.build | 2 +
> include/hw/arm/fsl-imx8mm.h | 156 ++++++++++++++
> 7 files changed, 711 insertions(+)
> create mode 100644 docs/system/arm/imx8mm-evk.rst
> create mode 100644 hw/arm/fsl-imx8mm.c
> create mode 100644 hw/arm/imx8mm-evk.c
> create mode 100644 include/hw/arm/fsl-imx8mm.h
>
>diff --git a/docs/system/arm/imx8mm-evk.rst b/docs/system/arm/imx8mm-evk.rst
>new file mode 100644
>index 0000000000..61d28ebf72
>--- /dev/null
>+++ b/docs/system/arm/imx8mm-evk.rst
>@@ -0,0 +1,70 @@
>+NXP i.MX 8MM Evaluation Kit (``imx8mm-evk``)
>+================================================
>+
>+The ``imx8mm-evk`` machine models the i.MX 8M Plus Evaluation Kit, based on an
s/Plus/Mini/ ?
>+i.MX 8MM SoC.
>+
>+Supported devices
>+-----------------
>+
>+The ``imx8mm-evk`` machine implements the following devices:
>+
>+ * Up to 4 Cortex-A53 cores
>+ * Generic Interrupt Controller (GICv3)
>+ * 4 UARTs
>+
>+Boot options
>+------------
>+
>+The ``imx8mm-evk`` machine can start a Linux kernel directly using the standard
>+``-kernel`` functionality.
>+
>+Direct Linux Kernel Boot
>+''''''''''''''''''''''''
>+
>+Probably the easiest way to get started with a whole Linux system on the machine
>+is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
>+of writing and involves two steps. First run the following commands in the
>+toplevel directory of the Buildroot source tree:
>+
>+.. code-block:: bash
>+
>+ $ make freescale_imx8mmevk_defconfig
>+ $ make
>+
>+Once finished successfully there is an ``output/image`` subfolder. Navigate into
>+it and resize the SD card image to a power of two:
>+
>+.. code-block:: bash
>+
>+ $ qemu-img resize sdcard.img 256M
>+
>+Now that everything is prepared the machine can be started as follows:
>+
>+.. code-block:: bash
>+
>+ $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 3G \
>+ -display none -serial null -serial stdio \
>+ -kernel Image \
>+ -dtb imx8mm-evk.dtb \
>+ -append "root=/dev/mmcblk2p2" \
>+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>+
>+
>+KVM Acceleration
>+----------------
>+
>+To enable hardware-assisted acceleration via KVM, append
>+``-accel kvm -cpu host`` to the command line. While this speeds up performance
`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc.
>+significantly, be aware of the following limitations:
>+
>+* The ``imx8mm-evk`` machine is not included under the "virtualization use case"
>+ of :doc:`QEMU's security policy </system/security>`. This means that you
>+ should not trust that it can contain malicious guests, whether it is run
>+ using TCG or KVM. If you don't trust your guests and you're relying on QEMU to
>+ be the security boundary, you want to choose another machine such as ``virt``.
>+* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
>+ This is a limitation of KVM and may not work with guests with a tight
>+ dependency on Cortex-A53.
>+* No EL2 and EL3 exception levels are available which is also a KVM limitation.
>+ Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.
>diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
>index a96d1867df..d6a4b5bb00 100644
>--- a/docs/system/target-arm.rst
>+++ b/docs/system/target-arm.rst
>@@ -97,6 +97,7 @@ Board-specific documentation
> arm/mcimx6ul-evk
> arm/mcimx7d-sabre
> arm/imx8mp-evk
>+ arm/imx8mm-evk
> arm/orangepi
> arm/raspi
> arm/collie
>diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>index 0cdeb60f1f..7c66f3c3cd 100644
>--- a/hw/arm/Kconfig
>+++ b/hw/arm/Kconfig
>@@ -626,6 +626,18 @@ config FSL_IMX8MP_EVK
> depends on TCG || KVM
> select FSL_IMX8MP
>
>+config FSL_IMX8MM
>+ bool
>+ select ARM_GIC
>+ select IMX
>+
>+config FSL_IMX8MM_EVK
>+ bool
>+ default y
>+ depends on AARCH64
>+ depends on TCG || KVM
>+ select FSL_IMX8MM
>+
> config ARM_SMMUV3
> bool
>
>diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c
>new file mode 100644
>index 0000000000..9c8acc1e99
>--- /dev/null
>+++ b/hw/arm/fsl-imx8mm.c
>@@ -0,0 +1,363 @@
>+/*
>+ * i.MX 8MM SoC Implementation
>+ *
>+ * Based on hw/arm/fsl-imx6.c
>+ *
>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#include "qemu/osdep.h"
>+#include "system/address-spaces.h"
>+#include "hw/arm/bsa.h"
>+#include "hw/arm/fsl-imx8mm.h"
>+#include "hw/misc/unimp.h"
>+#include "hw/boards.h"
>+#include "system/kvm.h"
>+#include "system/system.h"
>+#include "target/arm/cpu.h"
>+#include "target/arm/cpu-qom.h"
>+#include "target/arm/kvm_arm.h"
>+#include "qapi/error.h"
>+#include "qobject/qlist.h"
>+
>+static const struct {
>+ hwaddr addr;
>+ size_t size;
>+ const char *name;
>+} fsl_imx8mm_memmap[] = {
>+ [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
>+ [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
>+ [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
>+ [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
>+ [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
>+ [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
>+ [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
>+ [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
>+ [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
>+ [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
>+ [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
>+ [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
>+ [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
>+ [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
>+ [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
>+ [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
>+ [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
>+ [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
>+ [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
>+ [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
>+
>+ /* AIPS-4 Begin */
>+ [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
>+ [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
>+ [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
>+ [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
>+ [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
>+ [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
>+ [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
>+ /* AIPS-4 End */
>+
>+ [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
>+
>+ /* AIPS-3 Begin */
>+ [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
>+ [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
>+ [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
>+ [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
>+ [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
>+ [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
>+ [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
>+ [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
>+ [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
>+ [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
>+ [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
>+ [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
>+ [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
>+ [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
>+ [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
>+ [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
>+ [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
>+ [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
>+ [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
>+ [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
>+ [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
>+ [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
>+ [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
>+ /* AIPS-3 End */
>+
>+ /* AIPS-2 Begin */
>+ [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
>+ [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
>+ [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
>+ [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
>+ [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
>+ [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
>+ [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
>+ [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
>+ [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
>+ [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
>+ [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
>+ [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
>+ [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
>+ [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
>+ /* AIPS-2 End */
>+
>+ /* AIPS-1 Begin */
>+ [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
>+ [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
>+ [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
>+ [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
>+ [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
>+ [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
>+ [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
>+ [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
>+ [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
>+ [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
>+ [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
>+ [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
>+ [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
>+ [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
>+ [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
>+ [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
>+ [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
>+ [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
>+ [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
>+ [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
>+ [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
>+ [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
>+ [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
>+ [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
>+ [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
>+ [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
>+ [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
>+ [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
>+ [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
>+ [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
>+ [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
>+ [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
>+ [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
>+
>+ /* AIPS-1 End */
>+
>+ [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
>+ [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
>+ [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
>+ [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
>+ [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
>+ [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
>+ [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
>+ [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
>+ [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
>+ [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
>+};
>+
>+static void fsl_imx8mm_init(Object *obj)
>+{
>+ MachineState *ms = MACHINE(qdev_get_machine());
>+ FslImx8mmState *s = FSL_IMX8MM(obj);
>+ const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
>+ int i;
>+
>+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
>+ g_autofree char *name = g_strdup_printf("cpu%d", i);
>+ object_initialize_child(obj, name, &s->cpu[i], cpu_type);
>+ }
>+
>+ object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
>+
>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
>+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>+ }
>+
>+}
>+
>+static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
>+{
>+ MachineState *ms = MACHINE(qdev_get_machine());
>+ FslImx8mmState *s = FSL_IMX8MM(dev);
>+ DeviceState *gicdev = DEVICE(&s->gic);
>+ int i;
>+
>+ if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
>+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>+ TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
>+ return;
>+ }
>+
>+ /* CPUs */
>+ for (i = 0; i < ms->smp.cpus; i++) {
>+ /* On uniprocessor, the CBAR is set to 0 */
>+ if (ms->smp.cpus > 1 &&
>+ object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
>+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
>+ &error_abort);
>+ }
>+
>+ /*
>+ * CNTFID0 base frequency in Hz of system counter
>+ */
>+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>+ &error_abort);
>+
>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
>+ !kvm_enabled(), &error_abort);
>+ }
>+
>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
>+ !kvm_enabled(), &error_abort);
>+ }
>+
>+ if (i) {
>+ /*
>+ * Secondary CPUs start in powered-down state (and can be
>+ * powered up via the SRC system reset controller)
>+ */
>+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
>+ true, &error_abort);
>+ }
>+
>+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
>+ return;
>+ }
>+ }
>+
>+ /* GIC */
>+ {
>+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
>+ QList *redist_region_count;
>+ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
>+
>+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
>+ qdev_prop_set_uint32(gicdev, "num-irq",
>+ FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
>+ redist_region_count = qlist_new();
>+ qlist_append_int(redist_region_count, ms->smp.cpus);
>+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
>+ object_property_set_link(OBJECT(&s->gic), "sysmem",
>+ OBJECT(get_system_memory()), &error_fatal);
>+ if (!sysbus_realize(gicsbd, errp)) {
>+ return;
>+ }
>+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
>+ sysbus_mmio_map(gicsbd, 1, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
>+
>+ /*
>+ * Wire the outputs from each CPU's generic timer and the GICv3
>+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
>+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
>+ */
>+ for (i = 0; i < ms->smp.cpus; i++) {
>+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
>+ int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
>+ qemu_irq irq;
>+
>+ /*
>+ * Mapping from the output timer irq lines from the CPU to the
>+ * GIC PPI inputs.
>+ */
>+ static const int timer_irqs[] = {
>+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
>+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
>+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
>+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
>+ };
>+
>+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
>+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
>+ qdev_connect_gpio_out(cpudev, j, irq);
>+ }
>+
>+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
>+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
>+ 0, irq);
>+
>+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
>+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
>+
>+ sysbus_connect_irq(gicsbd, i,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
>+ sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
>+ sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
>+
>+ if (kvm_enabled()) {
>+ if (pmu) {
>+ assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
>+ if (kvm_irqchip_in_kernel()) {
>+ kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
>+ }
>+ kvm_arm_pmu_init(&s->cpu[i]);
>+ }
>+ }
>+ }
>+ }
>+
>+ /* UARTs */
>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>+ struct {
>+ hwaddr addr;
>+ unsigned int irq;
>+ } serial_table[FSL_IMX8MM_NUM_UARTS] = {
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
>+ };
>+
>+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
>+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
>+ return;
>+ }
>+
>+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
>+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
>+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
>+ }
>+
>+ /* Unimplemented devices */
>+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
>+ switch (i) {
>+ case FSL_IMX8MM_GIC_DIST:
>+ case FSL_IMX8MM_GIC_REDIST:
>+ case FSL_IMX8MM_RAM:
>+ case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
>+ /* device implemented and treated above */
>+ break;
>+
>+ default:
>+ create_unimplemented_device(fsl_imx8mm_memmap[i].name,
>+ fsl_imx8mm_memmap[i].addr,
>+ fsl_imx8mm_memmap[i].size);
>+ break;
>+ }
>+ }
>+}
>+
>+static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data)
>+{
>+ DeviceClass *dc = DEVICE_CLASS(oc);
>+
>+ dc->realize = fsl_imx8mm_realize;
>+
>+ dc->desc = "i.MX 8MM SoC";
>+}
>+
>+static const TypeInfo fsl_imx8mm_types[] = {
>+ {
>+ .name = TYPE_FSL_IMX8MM,
>+ .parent = TYPE_SYS_BUS_DEVICE,
>+ .instance_size = sizeof(FslImx8mmState),
>+ .instance_init = fsl_imx8mm_init,
>+ .class_init = fsl_imx8mm_class_init,
>+ },
>+};
>+
>+DEFINE_TYPES(fsl_imx8mm_types)
>diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c
>new file mode 100644
>index 0000000000..cfb42fe464
>--- /dev/null
>+++ b/hw/arm/imx8mm-evk.c
>@@ -0,0 +1,107 @@
>+/*
>+ * NXP i.MX 8MM Evaluation Kit System Emulation
>+ *
>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#include "qemu/osdep.h"
>+#include "system/address-spaces.h"
>+#include "hw/arm/boot.h"
>+#include "hw/arm/fsl-imx8mm.h"
>+#include "hw/arm/machines-qom.h"
>+#include "hw/boards.h"
>+#include "hw/qdev-properties.h"
>+#include "system/kvm.h"
>+#include "system/qtest.h"
>+#include "qemu/error-report.h"
>+#include "qapi/error.h"
>+#include <libfdt.h>
>+
>+static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info, void *fdt)
>+{
>+ int i, offset;
>+
>+ /* Temporarily disable following nodes until they are implemented */
>+ const char *nodes_to_remove[] = {
>+ "nxp,imx8mm-fspi",
>+ };
>+
>+ for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
>+ const char *dev_str = nodes_to_remove[i];
>+
>+ offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
>+ while (offset >= 0) {
>+ fdt_nop_node(fdt, offset);
>+ offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
>+ }
>+ }
>+
>+ /* Remove cpu-idle-states property from CPU nodes */
>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
>+ while (offset >= 0) {
>+ fdt_nop_property(fdt, offset, "cpu-idle-states");
>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
>+ }
Removing the idle-states ptoperties is only needed since the CPU goes into deep sleep mode during boot and is unable to wake up, even with an imx_sysctr implementation <https://github.com/shentok/qemu/blob/imx8mp/hw/timer/imx_sysctr.c>. Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful.
Thanks,
Bernhard
>+
>+ if (kvm_enabled()) {
>+ /* Use system counter frequency from host CPU to fix time in guest */
>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
>+ while (offset >= 0) {
>+ fdt_nop_property(fdt, offset, "clock-frequency");
>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
>+ }
>+ }
>+}
>+
>+static void imx8mm_evk_init(MachineState *machine)
>+{
>+ static struct arm_boot_info boot_info;
>+ FslImx8mmState *s;
>+
>+ if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
>+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
>+ machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
>+ exit(1);
>+ }
>+
>+ boot_info = (struct arm_boot_info) {
>+ .loader_start = FSL_IMX8MM_RAM_START,
>+ .board_id = -1,
>+ .ram_size = machine->ram_size,
>+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
>+ .modify_dtb = imx8mm_evk_modify_dtb,
>+ };
>+
>+ s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
>+ 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_IMX8MM_RAM_START,
>+ machine->ram);
>+
>+ if (!qtest_enabled()) {
>+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
>+ }
>+}
>+
>+static const char *imx8mm_evk_get_default_cpu_type(const MachineState *ms)
>+{
>+ if (kvm_enabled()) {
>+ return ARM_CPU_TYPE_NAME("host");
>+ }
>+
>+ return ARM_CPU_TYPE_NAME("cortex-a53");
>+}
>+
>+static void imx8mm_evk_machine_init(MachineClass *mc)
>+{
>+ mc->desc = "NXP i.MX 8MM EVK Board";
>+ mc->init = imx8mm_evk_init;
>+ mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
>+ mc->default_ram_id = "imx8mm-evk.ram";
>+ mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type;
>+}
>+
>+DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
>diff --git a/hw/arm/meson.build b/hw/arm/meson.build
>index aeaf654790..12ecb824cc 100644
>--- a/hw/arm/meson.build
>+++ b/hw/arm/meson.build
>@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true: files('fsl-imx8mm.c'))
>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true: files('imx8mm-evk.c'))
> arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
> arm_common_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
>diff --git a/include/hw/arm/fsl-imx8mm.h b/include/hw/arm/fsl-imx8mm.h
>new file mode 100644
>index 0000000000..aa954ea00b
>--- /dev/null
>+++ b/include/hw/arm/fsl-imx8mm.h
>@@ -0,0 +1,156 @@
>+/*
>+ * i.MX 8MM SoC Definitions
>+ *
>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later
>+ */
>+
>+#ifndef FSL_IMX8MM_H
>+#define FSL_IMX8MM_H
>+
>+#include "cpu.h"
>+#include "hw/char/imx_serial.h"
>+#include "hw/intc/arm_gicv3_common.h"
>+#include "qom/object.h"
>+#include "qemu/units.h"
>+
>+#define TYPE_FSL_IMX8MM "fsl-imx8mm"
>+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
>+
>+#define FSL_IMX8MM_RAM_START 0x40000000
>+#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
>+
>+enum FslImx8mmConfiguration {
>+ FSL_IMX8MM_NUM_CPUS = 4,
>+ FSL_IMX8MM_NUM_IRQS = 128,
>+ FSL_IMX8MM_NUM_UARTS = 4,
>+};
>+
>+struct FslImx8mmState {
>+ SysBusDevice parent_obj;
>+
>+ ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
>+ GICv3State gic;
>+ IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
>+};
>+
>+enum FslImx8mmMemoryRegions {
>+ FSL_IMX8MM_A53_DAP,
>+ FSL_IMX8MM_AIPS1_CONFIGURATION,
>+ FSL_IMX8MM_AIPS2_CONFIGURATION,
>+ FSL_IMX8MM_AIPS3_CONFIGURATION,
>+ FSL_IMX8MM_AIPS4_CONFIGURATION,
>+ FSL_IMX8MM_ANA_OSC,
>+ FSL_IMX8MM_ANA_PLL,
>+ FSL_IMX8MM_ANA_TSENSOR,
>+ FSL_IMX8MM_APBH_DMA,
>+ FSL_IMX8MM_BOOT_ROM,
>+ FSL_IMX8MM_BOOT_ROM_PROTECTED,
>+ FSL_IMX8MM_CAAM,
>+ FSL_IMX8MM_CAAM_MEM,
>+ FSL_IMX8MM_CCM,
>+ FSL_IMX8MM_CSU,
>+ FSL_IMX8MM_DDR_CTL,
>+ FSL_IMX8MM_DDR_PERF_MON,
>+ FSL_IMX8MM_DDR_PHY,
>+ FSL_IMX8MM_DDR_PHY_BROADCAST,
>+ FSL_IMX8MM_ECSPI1,
>+ FSL_IMX8MM_ECSPI2,
>+ FSL_IMX8MM_ECSPI3,
>+ FSL_IMX8MM_ENET1,
>+ FSL_IMX8MM_GIC_DIST,
>+ FSL_IMX8MM_GIC_REDIST,
>+ FSL_IMX8MM_GPC,
>+ FSL_IMX8MM_GPIO1,
>+ FSL_IMX8MM_GPIO2,
>+ FSL_IMX8MM_GPIO3,
>+ FSL_IMX8MM_GPIO4,
>+ FSL_IMX8MM_GPIO5,
>+ FSL_IMX8MM_GPT1,
>+ FSL_IMX8MM_GPT2,
>+ FSL_IMX8MM_GPT3,
>+ FSL_IMX8MM_GPT4,
>+ FSL_IMX8MM_GPT5,
>+ FSL_IMX8MM_GPT6,
>+ FSL_IMX8MM_GPU2D,
>+ FSL_IMX8MM_I2C1,
>+ FSL_IMX8MM_I2C2,
>+ FSL_IMX8MM_I2C3,
>+ FSL_IMX8MM_I2C4,
>+ FSL_IMX8MM_INTERCONNECT,
>+ FSL_IMX8MM_IOMUXC,
>+ FSL_IMX8MM_IOMUXC_GPR,
>+ FSL_IMX8MM_MEDIA_BLK_CTL,
>+ FSL_IMX8MM_LCDIF,
>+ FSL_IMX8MM_MIPI_CSI,
>+ FSL_IMX8MM_MIPI_DSI,
>+ FSL_IMX8MM_MU_A,
>+ FSL_IMX8MM_MU_B,
>+ FSL_IMX8MM_OCOTP_CTRL,
>+ FSL_IMX8MM_OCRAM,
>+ FSL_IMX8MM_OCRAM_S,
>+ FSL_IMX8MM_PCIE1,
>+ FSL_IMX8MM_PCIE1_MEM,
>+ FSL_IMX8MM_PCIE_PHY1,
>+ FSL_IMX8MM_PERFMON1,
>+ FSL_IMX8MM_PERFMON2,
>+ FSL_IMX8MM_PWM1,
>+ FSL_IMX8MM_PWM2,
>+ FSL_IMX8MM_PWM3,
>+ FSL_IMX8MM_PWM4,
>+ FSL_IMX8MM_QOSC,
>+ FSL_IMX8MM_QSPI,
>+ FSL_IMX8MM_QSPI1_RX_BUFFER,
>+ FSL_IMX8MM_QSPI1_TX_BUFFER,
>+ FSL_IMX8MM_QSPI_MEM,
>+ FSL_IMX8MM_RAM,
>+ FSL_IMX8MM_RDC,
>+ FSL_IMX8MM_SAI1,
>+ FSL_IMX8MM_SAI2,
>+ FSL_IMX8MM_SAI3,
>+ FSL_IMX8MM_SAI5,
>+ FSL_IMX8MM_SAI6,
>+ FSL_IMX8MM_SDMA1,
>+ FSL_IMX8MM_SDMA2,
>+ FSL_IMX8MM_SDMA3,
>+ FSL_IMX8MM_SEMAPHORE1,
>+ FSL_IMX8MM_SEMAPHORE2,
>+ FSL_IMX8MM_SEMAPHORE_HS,
>+ FSL_IMX8MM_SNVS_HP,
>+ FSL_IMX8MM_SPBA1,
>+ FSL_IMX8MM_SRC,
>+ FSL_IMX8MM_SYSCNT_CMP,
>+ FSL_IMX8MM_SYSCNT_CTRL,
>+ FSL_IMX8MM_SYSCNT_RD,
>+ FSL_IMX8MM_TCM_DTCM,
>+ FSL_IMX8MM_TCM_ITCM,
>+ FSL_IMX8MM_TZASC,
>+ FSL_IMX8MM_UART1,
>+ FSL_IMX8MM_UART2,
>+ FSL_IMX8MM_UART3,
>+ FSL_IMX8MM_UART4,
>+ FSL_IMX8MM_USB1,
>+ FSL_IMX8MM_USB2,
>+ FSL_IMX8MM_USB1_OTG,
>+ FSL_IMX8MM_USB2_OTG,
>+ FSL_IMX8MM_USDHC1,
>+ FSL_IMX8MM_USDHC2,
>+ FSL_IMX8MM_USDHC3,
>+ FSL_IMX8MM_VPU,
>+ FSL_IMX8MM_VPU_BLK_CTRL,
>+ FSL_IMX8MM_VPU_G1_DECODER,
>+ FSL_IMX8MM_VPU_G2_DECODER,
>+ FSL_IMX8MM_WDOG1,
>+ FSL_IMX8MM_WDOG2,
>+ FSL_IMX8MM_WDOG3,
>+};
>+
>+enum FslImx8mmIrqs {
>+ FSL_IMX8MM_UART1_IRQ = 26,
>+ FSL_IMX8MM_UART2_IRQ = 27,
>+ FSL_IMX8MM_UART3_IRQ = 28,
>+ FSL_IMX8MM_UART4_IRQ = 29,
>+};
>+
>+#endif /* FSL_IMX8MM_H */
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-11 23:21 ` Bernhard Beschow
@ 2025-11-12 6:58 ` Gaurav Sharma
2025-11-12 7:05 ` Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-12 6:58 UTC (permalink / raw)
To: Bernhard Beschow, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Thank you for reviewing Bernhard. Yes, iMX8MM is very close to iMX8MP that's why I chose to stick to that structure.
" Looks like these lists are sorted alphabetically. Shall we preserve that?"
-- yes "tests_aarch64_system_thorough" should be sorted alphabetically preserving the original order - - will modify it in v2 patch
"This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway"
-- yes, I just found out in the console log. The test was giving a false positive. Thank you for the heads up! I have now modified it to fetch the dtb from the Debian stable repository. Verified it's working correctly via console log
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
-- do you mean the DTB magic "d00dfeed" instead of "d00df00d"? Also, while I was analysing the DTB offset of the mainlined imx8mp functional testing 'disk.raw' which has debian-12-generic-arm64-20231210-1590. The script mentions the DTB_OFFSET at 0x64F51000. Dumping this offset using xxd[also verified it via hex editor]:-
# xxd -s 0x51000000 -l 4 disk.raw
51000000: 6cff 0060
It doesn't mention the DTB magic number at this offset. Please let me know if I am missing anything here .
Can we choose not to rely on the hardcoded offset and instead download the dtb from the Debian stable repository itself? This way the same functional test can be used easily for the future imx board porting as well.
Looking forward to your guidance.
-----Original Message-----
From: Bernhard Beschow <shentey@gmail.com>
Sent: 12 November 2025 04:51
To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
[You don't often get email from shentey@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Am 10. November 2025 11:22:57 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>Added script that would validate the iMX8MM emulation by checking the
>linux console log. If it succeeds, it will return:-
>
>ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
>
>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Hi Gaurav!
>Nice to see another imx8 machine being contributed! I'm impressed how close you stick to the imx8mp, both in terms of structuring this series as well as the code.
>I've built your series and ran the functional test. Comments below.
--
>---
> tests/functional/aarch64/meson.build | 2 +
> tests/functional/aarch64/test_imx8mm_evk.py | 67 +++++++++++++++++++++
> 2 files changed, 69 insertions(+)
> create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
>
>diff --git a/tests/functional/aarch64/meson.build
>b/tests/functional/aarch64/meson.build
>index 5ad52f93e1..31ecedbf6f 100644
>--- a/tests/functional/aarch64/meson.build
>+++ b/tests/functional/aarch64/meson.build
>@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
> 'aspeed_ast2700fc' : 600,
> 'device_passthrough' : 720,
> 'imx8mp_evk' : 240,
>+ 'imx8mm_evk' : 240,
> 'raspi4' : 480,
> 'reverse_debug' : 180,
> 'rme_virt' : 1200,
>@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
> 'device_passthrough',
> 'hotplug_pci',
> 'imx8mp_evk',
>+ 'imx8mm_evk',
Looks like these lists are sorted alphabetically. Shall we preserve that?
> 'kvm',
> 'multiprocess',
> 'raspi3',
>diff --git a/tests/functional/aarch64/test_imx8mm_evk.py
>b/tests/functional/aarch64/test_imx8mm_evk.py
>new file mode 100755
>index 0000000000..d5eb43afc6
>--- /dev/null
>+++ b/tests/functional/aarch64/test_imx8mm_evk.py
>@@ -0,0 +1,67 @@
>+#!/usr/bin/env python3
>+#
>+# Functional test that boots a Linux kernel and checks the console # #
>+SPDX-License-Identifier: GPL-2.0-or-later
>+
>+from qemu_test import LinuxKernelTest, Asset
>+
>+class Imx8mmEvkMachine(LinuxKernelTest):
>+
>+ ASSET_IMAGE = Asset(
>+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
>+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
>+
>+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
>+
>+ KERNEL_OFFSET = 0x51000000
>+ KERNEL_SIZE = 32622528
>+ INITRD_OFFSET = 0x76000000
>+ INITRD_SIZE = 30987766
>+ DTB_OFFSET = 0x64F51000
This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway.
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
Best regards,
Bernhard
>+ DTB_SIZE = 45 * 1024
>+
>+ def extract(self, in_path, out_path, offset, size):
>+ try:
>+ with open(in_path, "rb") as source:
>+ source.seek(offset)
>+ data = source.read(size)
>+ with open(out_path, "wb") as target:
>+ target.write(data)
>+ except (IOError, ValueError) as e:
>+ self.log.error(f"Failed to extract {out_path}: {e}")
>+ raise
>+
>+ def setUp(self):
>+ super().setUp()
>+
>+ self.image_path = self.scratch_file("disk.raw")
>+ self.kernel_path = self.scratch_file("linux")
>+ self.initrd_path = self.scratch_file("initrd.zstd")
>+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
>+
>+ self.archive_extract(self.ASSET_IMAGE)
>+ self.extract(self.image_path, self.kernel_path,
>+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
>+ self.extract(self.image_path, self.initrd_path,
>+ self.INITRD_OFFSET, self.INITRD_SIZE)
>+ self.extract(self.image_path, self.dtb_path,
>+ self.DTB_OFFSET, self.DTB_SIZE)
>+
>+ def test_aarch64_imx8mm_evk_usdhc(self):
>+ self.require_accelerator("tcg")
>+ self.set_machine('imx8mm-evk')
>+ self.vm.set_console(console_index=1)
>+ self.vm.add_args('-m', '2G',
>+ '-smp', '4',
>+ '-kernel', self.kernel_path,
>+ '-initrd', self.initrd_path,
>+ '-dtb', self.dtb_path,
>+ '-append', 'root=/dev/mmcblk2p1',
>+ '-drive', f'file={self.image_path},if=sd,bus=2,'
>+
>+ 'format=raw,id=mmcblk2,snapshot=on')
>+
>+ self.vm.launch()
>+ self.wait_for_console_pattern('Welcome to ')
>+
>+if __name__ == '__main__':
>+ LinuxKernelTest.main()
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-12 6:58 ` [EXT] " Gaurav Sharma
@ 2025-11-12 7:05 ` Gaurav Sharma
2025-11-12 11:02 ` Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-12 7:05 UTC (permalink / raw)
To: Bernhard Beschow, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Sorry The correct xxd dump for dtb offset 0x64F51000:-
xxd -s 0x64F51000 -l 4 disk.raw
64f51000: e103 16aa ....
-----Original Message-----
From: Gaurav Sharma
Sent: 12 November 2025 12:28
To: 'Bernhard Beschow' <shentey@gmail.com>; qemu-devel@nongnu.org
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
Thank you for reviewing Bernhard. Yes, iMX8MM is very close to iMX8MP that's why I chose to stick to that structure.
" Looks like these lists are sorted alphabetically. Shall we preserve that?"
-- yes "tests_aarch64_system_thorough" should be sorted alphabetically preserving the original order - - will modify it in v2 patch
"This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway"
-- yes, I just found out in the console log. The test was giving a false positive. Thank you for the heads up! I have now modified it to fetch the dtb from the Debian stable repository. Verified it's working correctly via console log
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
-- do you mean the DTB magic "d00dfeed" instead of "d00df00d"? Also, while I was analysing the DTB offset of the mainlined imx8mp functional testing 'disk.raw' which has debian-12-generic-arm64-20231210-1590. The script mentions the DTB_OFFSET at 0x64F51000. Dumping this offset using xxd[also verified it via hex editor]:- # xxd -s 0x51000000 -l 4 disk.raw
51000000: 6cff 0060
It doesn't mention the DTB magic number at this offset. Please let me know if I am missing anything here .
Can we choose not to rely on the hardcoded offset and instead download the dtb from the Debian stable repository itself? This way the same functional test can be used easily for the future imx board porting as well.
Looking forward to your guidance.
-----Original Message-----
From: Bernhard Beschow <shentey@gmail.com>
Sent: 12 November 2025 04:51
To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
[You don't often get email from shentey@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Am 10. November 2025 11:22:57 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>Added script that would validate the iMX8MM emulation by checking the
>linux console log. If it succeeds, it will return:-
>
>ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
>
>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Hi Gaurav!
>Nice to see another imx8 machine being contributed! I'm impressed how close you stick to the imx8mp, both in terms of structuring this series as well as the code.
>I've built your series and ran the functional test. Comments below.
--
>---
> tests/functional/aarch64/meson.build | 2 +
> tests/functional/aarch64/test_imx8mm_evk.py | 67 +++++++++++++++++++++
> 2 files changed, 69 insertions(+)
> create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
>
>diff --git a/tests/functional/aarch64/meson.build
>b/tests/functional/aarch64/meson.build
>index 5ad52f93e1..31ecedbf6f 100644
>--- a/tests/functional/aarch64/meson.build
>+++ b/tests/functional/aarch64/meson.build
>@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
> 'aspeed_ast2700fc' : 600,
> 'device_passthrough' : 720,
> 'imx8mp_evk' : 240,
>+ 'imx8mm_evk' : 240,
> 'raspi4' : 480,
> 'reverse_debug' : 180,
> 'rme_virt' : 1200,
>@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
> 'device_passthrough',
> 'hotplug_pci',
> 'imx8mp_evk',
>+ 'imx8mm_evk',
Looks like these lists are sorted alphabetically. Shall we preserve that?
> 'kvm',
> 'multiprocess',
> 'raspi3',
>diff --git a/tests/functional/aarch64/test_imx8mm_evk.py
>b/tests/functional/aarch64/test_imx8mm_evk.py
>new file mode 100755
>index 0000000000..d5eb43afc6
>--- /dev/null
>+++ b/tests/functional/aarch64/test_imx8mm_evk.py
>@@ -0,0 +1,67 @@
>+#!/usr/bin/env python3
>+#
>+# Functional test that boots a Linux kernel and checks the console # #
>+SPDX-License-Identifier: GPL-2.0-or-later
>+
>+from qemu_test import LinuxKernelTest, Asset
>+
>+class Imx8mmEvkMachine(LinuxKernelTest):
>+
>+ ASSET_IMAGE = Asset(
>+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
>+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
>+
>+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
>+
>+ KERNEL_OFFSET = 0x51000000
>+ KERNEL_SIZE = 32622528
>+ INITRD_OFFSET = 0x76000000
>+ INITRD_SIZE = 30987766
>+ DTB_OFFSET = 0x64F51000
This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway.
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
Best regards,
Bernhard
>+ DTB_SIZE = 45 * 1024
>+
>+ def extract(self, in_path, out_path, offset, size):
>+ try:
>+ with open(in_path, "rb") as source:
>+ source.seek(offset)
>+ data = source.read(size)
>+ with open(out_path, "wb") as target:
>+ target.write(data)
>+ except (IOError, ValueError) as e:
>+ self.log.error(f"Failed to extract {out_path}: {e}")
>+ raise
>+
>+ def setUp(self):
>+ super().setUp()
>+
>+ self.image_path = self.scratch_file("disk.raw")
>+ self.kernel_path = self.scratch_file("linux")
>+ self.initrd_path = self.scratch_file("initrd.zstd")
>+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
>+
>+ self.archive_extract(self.ASSET_IMAGE)
>+ self.extract(self.image_path, self.kernel_path,
>+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
>+ self.extract(self.image_path, self.initrd_path,
>+ self.INITRD_OFFSET, self.INITRD_SIZE)
>+ self.extract(self.image_path, self.dtb_path,
>+ self.DTB_OFFSET, self.DTB_SIZE)
>+
>+ def test_aarch64_imx8mm_evk_usdhc(self):
>+ self.require_accelerator("tcg")
>+ self.set_machine('imx8mm-evk')
>+ self.vm.set_console(console_index=1)
>+ self.vm.add_args('-m', '2G',
>+ '-smp', '4',
>+ '-kernel', self.kernel_path,
>+ '-initrd', self.initrd_path,
>+ '-dtb', self.dtb_path,
>+ '-append', 'root=/dev/mmcblk2p1',
>+ '-drive', f'file={self.image_path},if=sd,bus=2,'
>+
>+ 'format=raw,id=mmcblk2,snapshot=on')
>+
>+ self.vm.launch()
>+ self.wait_for_console_pattern('Welcome to ')
>+
>+if __name__ == '__main__':
>+ LinuxKernelTest.main()
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-12 7:05 ` Gaurav Sharma
@ 2025-11-12 11:02 ` Gaurav Sharma
2025-11-12 21:46 ` Bernhard Beschow
0 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-12 11:02 UTC (permalink / raw)
To: Bernhard Beschow, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
@'Bernhard Beschow' looks like I was referring to the hex dump of a different Debian disk image. I have got the offset for iMX8MM now. I have tested it as well. The console looks good. Now the only question remains:- shall we continue using offset based method to extract dtb or download it from the cloud instead?
-----Original Message-----
From: Gaurav Sharma
Sent: 12 November 2025 12:35
To: 'Bernhard Beschow' <shentey@gmail.com>; 'qemu-devel@nongnu.org' <qemu-devel@nongnu.org>
Cc: 'pbonzini@redhat.com' <pbonzini@redhat.com>; 'peter.maydell@linaro.org' <peter.maydell@linaro.org>
Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
Sorry The correct xxd dump for dtb offset 0x64F51000:- xxd -s 0x64F51000 -l 4 disk.raw
64f51000: e103 16aa ....
-----Original Message-----
From: Gaurav Sharma
Sent: 12 November 2025 12:28
To: 'Bernhard Beschow' <shentey@gmail.com>; qemu-devel@nongnu.org
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
Thank you for reviewing Bernhard. Yes, iMX8MM is very close to iMX8MP that's why I chose to stick to that structure.
" Looks like these lists are sorted alphabetically. Shall we preserve that?"
-- yes "tests_aarch64_system_thorough" should be sorted alphabetically preserving the original order - - will modify it in v2 patch
"This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway"
-- yes, I just found out in the console log. The test was giving a false positive. Thank you for the heads up! I have now modified it to fetch the dtb from the Debian stable repository. Verified it's working correctly via console log
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
-- do you mean the DTB magic "d00dfeed" instead of "d00df00d"? Also, while I was analysing the DTB offset of the mainlined imx8mp functional testing 'disk.raw' which has debian-12-generic-arm64-20231210-1590. The script mentions the DTB_OFFSET at 0x64F51000. Dumping this offset using xxd[also verified it via hex editor]:- # xxd -s 0x51000000 -l 4 disk.raw
51000000: 6cff 0060
It doesn't mention the DTB magic number at this offset. Please let me know if I am missing anything here .
Can we choose not to rely on the hardcoded offset and instead download the dtb from the Debian stable repository itself? This way the same functional test can be used easily for the future imx board porting as well.
Looking forward to your guidance.
-----Original Message-----
From: Bernhard Beschow <shentey@gmail.com>
Sent: 12 November 2025 04:51
To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
[You don't often get email from shentey@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Am 10. November 2025 11:22:57 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>Added script that would validate the iMX8MM emulation by checking the
>linux console log. If it succeeds, it will return:-
>
>ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
>
>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Hi Gaurav!
>Nice to see another imx8 machine being contributed! I'm impressed how close you stick to the imx8mp, both in terms of structuring this series as well as the code.
>I've built your series and ran the functional test. Comments below.
--
>---
> tests/functional/aarch64/meson.build | 2 +
> tests/functional/aarch64/test_imx8mm_evk.py | 67 +++++++++++++++++++++
> 2 files changed, 69 insertions(+)
> create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
>
>diff --git a/tests/functional/aarch64/meson.build
>b/tests/functional/aarch64/meson.build
>index 5ad52f93e1..31ecedbf6f 100644
>--- a/tests/functional/aarch64/meson.build
>+++ b/tests/functional/aarch64/meson.build
>@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
> 'aspeed_ast2700fc' : 600,
> 'device_passthrough' : 720,
> 'imx8mp_evk' : 240,
>+ 'imx8mm_evk' : 240,
> 'raspi4' : 480,
> 'reverse_debug' : 180,
> 'rme_virt' : 1200,
>@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
> 'device_passthrough',
> 'hotplug_pci',
> 'imx8mp_evk',
>+ 'imx8mm_evk',
Looks like these lists are sorted alphabetically. Shall we preserve that?
> 'kvm',
> 'multiprocess',
> 'raspi3',
>diff --git a/tests/functional/aarch64/test_imx8mm_evk.py
>b/tests/functional/aarch64/test_imx8mm_evk.py
>new file mode 100755
>index 0000000000..d5eb43afc6
>--- /dev/null
>+++ b/tests/functional/aarch64/test_imx8mm_evk.py
>@@ -0,0 +1,67 @@
>+#!/usr/bin/env python3
>+#
>+# Functional test that boots a Linux kernel and checks the console # #
>+SPDX-License-Identifier: GPL-2.0-or-later
>+
>+from qemu_test import LinuxKernelTest, Asset
>+
>+class Imx8mmEvkMachine(LinuxKernelTest):
>+
>+ ASSET_IMAGE = Asset(
>+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
>+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
>+
>+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
>+
>+ KERNEL_OFFSET = 0x51000000
>+ KERNEL_SIZE = 32622528
>+ INITRD_OFFSET = 0x76000000
>+ INITRD_SIZE = 30987766
>+ DTB_OFFSET = 0x64F51000
This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway.
What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
Best regards,
Bernhard
>+ DTB_SIZE = 45 * 1024
>+
>+ def extract(self, in_path, out_path, offset, size):
>+ try:
>+ with open(in_path, "rb") as source:
>+ source.seek(offset)
>+ data = source.read(size)
>+ with open(out_path, "wb") as target:
>+ target.write(data)
>+ except (IOError, ValueError) as e:
>+ self.log.error(f"Failed to extract {out_path}: {e}")
>+ raise
>+
>+ def setUp(self):
>+ super().setUp()
>+
>+ self.image_path = self.scratch_file("disk.raw")
>+ self.kernel_path = self.scratch_file("linux")
>+ self.initrd_path = self.scratch_file("initrd.zstd")
>+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
>+
>+ self.archive_extract(self.ASSET_IMAGE)
>+ self.extract(self.image_path, self.kernel_path,
>+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
>+ self.extract(self.image_path, self.initrd_path,
>+ self.INITRD_OFFSET, self.INITRD_SIZE)
>+ self.extract(self.image_path, self.dtb_path,
>+ self.DTB_OFFSET, self.DTB_SIZE)
>+
>+ def test_aarch64_imx8mm_evk_usdhc(self):
>+ self.require_accelerator("tcg")
>+ self.set_machine('imx8mm-evk')
>+ self.vm.set_console(console_index=1)
>+ self.vm.add_args('-m', '2G',
>+ '-smp', '4',
>+ '-kernel', self.kernel_path,
>+ '-initrd', self.initrd_path,
>+ '-dtb', self.dtb_path,
>+ '-append', 'root=/dev/mmcblk2p1',
>+ '-drive', f'file={self.image_path},if=sd,bus=2,'
>+
>+ 'format=raw,id=mmcblk2,snapshot=on')
>+
>+ self.vm.launch()
>+ self.wait_for_console_pattern('Welcome to ')
>+
>+if __name__ == '__main__':
>+ LinuxKernelTest.main()
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-12 11:02 ` Gaurav Sharma
@ 2025-11-12 21:46 ` Bernhard Beschow
2025-11-13 3:03 ` Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Bernhard Beschow @ 2025-11-12 21:46 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Am 12. November 2025 11:02:13 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>@'Bernhard Beschow' looks like I was referring to the hex dump of a different Debian disk image. I have got the offset for iMX8MM now. I have tested it as well. The console looks good. Now the only question remains:- shall we continue using offset based method to extract dtb or download it from the cloud instead?
Nice! I'd slightly prefer extracring the DTB from the image for consistency and to have only one URL that could break in the future. Does this work for you?
>
>-----Original Message-----
>From: Gaurav Sharma
>Sent: 12 November 2025 12:35
>To: 'Bernhard Beschow' <shentey@gmail.com>; 'qemu-devel@nongnu.org' <qemu-devel@nongnu.org>
>Cc: 'pbonzini@redhat.com' <pbonzini@redhat.com>; 'peter.maydell@linaro.org' <peter.maydell@linaro.org>
>Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
>
>Sorry The correct xxd dump for dtb offset 0x64F51000:- xxd -s 0x64F51000 -l 4 disk.raw
>64f51000: e103 16aa ....
>
>
>-----Original Message-----
>From: Gaurav Sharma
>Sent: 12 November 2025 12:28
>To: 'Bernhard Beschow' <shentey@gmail.com>; qemu-devel@nongnu.org
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
>
>Thank you for reviewing Bernhard. Yes, iMX8MM is very close to iMX8MP that's why I chose to stick to that structure.
>
>" Looks like these lists are sorted alphabetically. Shall we preserve that?"
>
>-- yes "tests_aarch64_system_thorough" should be sorted alphabetically preserving the original order - - will modify it in v2 patch
>
>"This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway"
>
>-- yes, I just found out in the console log. The test was giving a false positive. Thank you for the heads up! I have now modified it to fetch the dtb from the Debian stable repository. Verified it's working correctly via console log
>
>What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
>
>-- do you mean the DTB magic "d00dfeed" instead of "d00df00d"? Also, while I was analysing the DTB offset of the mainlined imx8mp functional testing 'disk.raw' which has debian-12-generic-arm64-20231210-1590. The script mentions the DTB_OFFSET at 0x64F51000. Dumping this offset using xxd[also verified it via hex editor]:- # xxd -s 0x51000000 -l 4 disk.raw
>51000000: 6cff 0060
>It doesn't mention the DTB magic number at this offset. Please let me know if I am missing anything here .
>Can we choose not to rely on the hardcoded offset and instead download the dtb from the Debian stable repository itself? This way the same functional test can be used easily for the future imx board porting as well.
>Looking forward to your guidance.
>
>
>
>-----Original Message-----
>From: Bernhard Beschow <shentey@gmail.com>
>Sent: 12 November 2025 04:51
>To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
>
>[You don't often get email from shentey@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
>Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
>
>
>Am 10. November 2025 11:22:57 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>>Added script that would validate the iMX8MM emulation by checking the
>>linux console log. If it succeeds, it will return:-
>>
>>ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
>>
>>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>
>>Hi Gaurav!
>
>>Nice to see another imx8 machine being contributed! I'm impressed how close you stick to the imx8mp, both in terms of structuring this series as well as the code.
>
>>I've built your series and ran the functional test. Comments below.
>
>
>
>
>--
>
>>---
>> tests/functional/aarch64/meson.build | 2 +
>> tests/functional/aarch64/test_imx8mm_evk.py | 67 +++++++++++++++++++++
>> 2 files changed, 69 insertions(+)
>> create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
>>
>>diff --git a/tests/functional/aarch64/meson.build
>>b/tests/functional/aarch64/meson.build
>>index 5ad52f93e1..31ecedbf6f 100644
>>--- a/tests/functional/aarch64/meson.build
>>+++ b/tests/functional/aarch64/meson.build
>>@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
>> 'aspeed_ast2700fc' : 600,
>> 'device_passthrough' : 720,
>> 'imx8mp_evk' : 240,
>>+ 'imx8mm_evk' : 240,
>> 'raspi4' : 480,
>> 'reverse_debug' : 180,
>> 'rme_virt' : 1200,
>>@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
>> 'device_passthrough',
>> 'hotplug_pci',
>> 'imx8mp_evk',
>>+ 'imx8mm_evk',
>
>Looks like these lists are sorted alphabetically. Shall we preserve that?
>
>> 'kvm',
>> 'multiprocess',
>> 'raspi3',
>>diff --git a/tests/functional/aarch64/test_imx8mm_evk.py
>>b/tests/functional/aarch64/test_imx8mm_evk.py
>>new file mode 100755
>>index 0000000000..d5eb43afc6
>>--- /dev/null
>>+++ b/tests/functional/aarch64/test_imx8mm_evk.py
>>@@ -0,0 +1,67 @@
>>+#!/usr/bin/env python3
>>+#
>>+# Functional test that boots a Linux kernel and checks the console # #
>>+SPDX-License-Identifier: GPL-2.0-or-later
>>+
>>+from qemu_test import LinuxKernelTest, Asset
>>+
>>+class Imx8mmEvkMachine(LinuxKernelTest):
>>+
>>+ ASSET_IMAGE = Asset(
>>+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
>>+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
>>+
>>+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
>>+
>>+ KERNEL_OFFSET = 0x51000000
>>+ KERNEL_SIZE = 32622528
>>+ INITRD_OFFSET = 0x76000000
>>+ INITRD_SIZE = 30987766
>>+ DTB_OFFSET = 0x64F51000
>
>This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway.
>
>What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
>
>Best regards,
>Bernhard
>
>>+ DTB_SIZE = 45 * 1024
>>+
>>+ def extract(self, in_path, out_path, offset, size):
>>+ try:
>>+ with open(in_path, "rb") as source:
>>+ source.seek(offset)
>>+ data = source.read(size)
>>+ with open(out_path, "wb") as target:
>>+ target.write(data)
>>+ except (IOError, ValueError) as e:
>>+ self.log.error(f"Failed to extract {out_path}: {e}")
>>+ raise
>>+
>>+ def setUp(self):
>>+ super().setUp()
>>+
>>+ self.image_path = self.scratch_file("disk.raw")
>>+ self.kernel_path = self.scratch_file("linux")
>>+ self.initrd_path = self.scratch_file("initrd.zstd")
>>+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
>>+
>>+ self.archive_extract(self.ASSET_IMAGE)
>>+ self.extract(self.image_path, self.kernel_path,
>>+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
>>+ self.extract(self.image_path, self.initrd_path,
>>+ self.INITRD_OFFSET, self.INITRD_SIZE)
>>+ self.extract(self.image_path, self.dtb_path,
>>+ self.DTB_OFFSET, self.DTB_SIZE)
>>+
>>+ def test_aarch64_imx8mm_evk_usdhc(self):
>>+ self.require_accelerator("tcg")
>>+ self.set_machine('imx8mm-evk')
>>+ self.vm.set_console(console_index=1)
>>+ self.vm.add_args('-m', '2G',
>>+ '-smp', '4',
>>+ '-kernel', self.kernel_path,
>>+ '-initrd', self.initrd_path,
>>+ '-dtb', self.dtb_path,
>>+ '-append', 'root=/dev/mmcblk2p1',
>>+ '-drive', f'file={self.image_path},if=sd,bus=2,'
>>+
>>+ 'format=raw,id=mmcblk2,snapshot=on')
>>+
>>+ self.vm.launch()
>>+ self.wait_for_console_pattern('Welcome to ')
>>+
>>+if __name__ == '__main__':
>>+ LinuxKernelTest.main()
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
2025-11-12 21:46 ` Bernhard Beschow
@ 2025-11-13 3:03 ` Gaurav Sharma
0 siblings, 0 replies; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-13 3:03 UTC (permalink / raw)
To: Bernhard Beschow, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Noted. Yes, sounds good. I will make this change in v2 patch.
-----Original Message-----
From: Bernhard Beschow <shentey@gmail.com>
Sent: 13 November 2025 03:17
To: Gaurav Sharma <gaurav.sharma_7@nxp.com>; qemu-devel@nongnu.org
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Am 12. November 2025 11:02:13 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>@'Bernhard Beschow' looks like I was referring to the hex dump of a different Debian disk image. I have got the offset for iMX8MM now. I have tested it as well. The console looks good. Now the only question remains:- shall we continue using offset based method to extract dtb or download it from the cloud instead?
Nice! I'd slightly prefer extracring the DTB from the image for consistency and to have only one URL that could break in the future. Does this work for you?
>
>-----Original Message-----
>From: Gaurav Sharma
>Sent: 12 November 2025 12:35
>To: 'Bernhard Beschow' <shentey@gmail.com>; 'qemu-devel@nongnu.org'
><qemu-devel@nongnu.org>
>Cc: 'pbonzini@redhat.com' <pbonzini@redhat.com>;
>'peter.maydell@linaro.org' <peter.maydell@linaro.org>
>Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding
>functional testing of iMX8MM emulation
>
>Sorry The correct xxd dump for dtb offset 0x64F51000:- xxd -s 0x64F51000 -l 4 disk.raw
>64f51000: e103 16aa ....
>
>
>-----Original Message-----
>From: Gaurav Sharma
>Sent: 12 November 2025 12:28
>To: 'Bernhard Beschow' <shentey@gmail.com>; qemu-devel@nongnu.org
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: RE: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding
>functional testing of iMX8MM emulation
>
>Thank you for reviewing Bernhard. Yes, iMX8MM is very close to iMX8MP that's why I chose to stick to that structure.
>
>" Looks like these lists are sorted alphabetically. Shall we preserve that?"
>
>-- yes "tests_aarch64_system_thorough" should be sorted alphabetically
>preserving the original order - - will modify it in v2 patch
>
>"This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway"
>
>-- yes, I just found out in the console log. The test was giving a
>false positive. Thank you for the heads up! I have now modified it to
>fetch the dtb from the Debian stable repository. Verified it's working
>correctly via console log
>
>What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
>
>-- do you mean the DTB magic "d00dfeed" instead of "d00df00d"? Also,
>while I was analysing the DTB offset of the mainlined imx8mp functional
>testing 'disk.raw' which has debian-12-generic-arm64-20231210-1590. The
>script mentions the DTB_OFFSET at 0x64F51000. Dumping this offset using
>xxd[also verified it via hex editor]:- # xxd -s 0x51000000 -l 4
>disk.raw
>51000000: 6cff 0060
>It doesn't mention the DTB magic number at this offset. Please let me know if I am missing anything here .
>Can we choose not to rely on the hardcoded offset and instead download the dtb from the Debian stable repository itself? This way the same functional test can be used easily for the future imx board porting as well.
>Looking forward to your guidance.
>
>
>
>-----Original Message-----
>From: Bernhard Beschow <shentey@gmail.com>
>Sent: 12 November 2025 04:51
>To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: [EXT] Re: [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional
>testing of iMX8MM emulation
>
>[You don't often get email from shentey@gmail.com. Learn why this is
>important at https://aka.ms/LearnAboutSenderIdentification ]
>
>Caution: This is an external email. Please take care when clicking
>links or opening attachments. When in doubt, report the message using
>the 'Report this email' button
>
>
>Am 10. November 2025 11:22:57 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>>Added script that would validate the iMX8MM emulation by checking the
>>linux console log. If it succeeds, it will return:-
>>
>>ok 1 test_imx8mm_evk.Imx8mmEvkMachine.test_aarch64_imx8mm_evk_usdhc
>>
>>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>
>>Hi Gaurav!
>
>>Nice to see another imx8 machine being contributed! I'm impressed how close you stick to the imx8mp, both in terms of structuring this series as well as the code.
>
>>I've built your series and ran the functional test. Comments below.
>
>
>
>
>--
>
>>---
>> tests/functional/aarch64/meson.build | 2 +
>> tests/functional/aarch64/test_imx8mm_evk.py | 67
>>+++++++++++++++++++++
>> 2 files changed, 69 insertions(+)
>> create mode 100755 tests/functional/aarch64/test_imx8mm_evk.py
>>
>>diff --git a/tests/functional/aarch64/meson.build
>>b/tests/functional/aarch64/meson.build
>>index 5ad52f93e1..31ecedbf6f 100644
>>--- a/tests/functional/aarch64/meson.build
>>+++ b/tests/functional/aarch64/meson.build
>>@@ -5,6 +5,7 @@ test_aarch64_timeouts = {
>> 'aspeed_ast2700fc' : 600,
>> 'device_passthrough' : 720,
>> 'imx8mp_evk' : 240,
>>+ 'imx8mm_evk' : 240,
>> 'raspi4' : 480,
>> 'reverse_debug' : 180,
>> 'rme_virt' : 1200,
>>@@ -28,6 +29,7 @@ tests_aarch64_system_thorough = [
>> 'device_passthrough',
>> 'hotplug_pci',
>> 'imx8mp_evk',
>>+ 'imx8mm_evk',
>
>Looks like these lists are sorted alphabetically. Shall we preserve that?
>
>> 'kvm',
>> 'multiprocess',
>> 'raspi3',
>>diff --git a/tests/functional/aarch64/test_imx8mm_evk.py
>>b/tests/functional/aarch64/test_imx8mm_evk.py
>>new file mode 100755
>>index 0000000000..d5eb43afc6
>>--- /dev/null
>>+++ b/tests/functional/aarch64/test_imx8mm_evk.py
>>@@ -0,0 +1,67 @@
>>+#!/usr/bin/env python3
>>+#
>>+# Functional test that boots a Linux kernel and checks the console #
>>+#
>>+SPDX-License-Identifier: GPL-2.0-or-later
>>+
>>+from qemu_test import LinuxKernelTest, Asset
>>+
>>+class Imx8mmEvkMachine(LinuxKernelTest):
>>+
>>+ ASSET_IMAGE = Asset(
>>+ ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
>>+ 'debian-12-generic-arm64-20231210-1590.tar.xz'),
>>+
>>+ '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
>>+
>>+ KERNEL_OFFSET = 0x51000000
>>+ KERNEL_SIZE = 32622528
>>+ INITRD_OFFSET = 0x76000000
>>+ INITRD_SIZE = 30987766
>>+ DTB_OFFSET = 0x64F51000
>
>This DTB offset is the one for the imx8mp-evk, and in fact the console log confirms it. Both machines seem to be so similar that the test passes anyway.
>
>What you need is the offset in the "disk.raw" image that gets extracted from above file. Open "disk.raw" in a hex editor and search for "imx8mm-evk", then determine the offset of the preceeding "d00df00d" DTB magic. That is your offset.
>
>Best regards,
>Bernhard
>
>>+ DTB_SIZE = 45 * 1024
>>+
>>+ def extract(self, in_path, out_path, offset, size):
>>+ try:
>>+ with open(in_path, "rb") as source:
>>+ source.seek(offset)
>>+ data = source.read(size)
>>+ with open(out_path, "wb") as target:
>>+ target.write(data)
>>+ except (IOError, ValueError) as e:
>>+ self.log.error(f"Failed to extract {out_path}: {e}")
>>+ raise
>>+
>>+ def setUp(self):
>>+ super().setUp()
>>+
>>+ self.image_path = self.scratch_file("disk.raw")
>>+ self.kernel_path = self.scratch_file("linux")
>>+ self.initrd_path = self.scratch_file("initrd.zstd")
>>+ self.dtb_path = self.scratch_file("imx8mm-evk.dtb")
>>+
>>+ self.archive_extract(self.ASSET_IMAGE)
>>+ self.extract(self.image_path, self.kernel_path,
>>+ self.KERNEL_OFFSET, self.KERNEL_SIZE)
>>+ self.extract(self.image_path, self.initrd_path,
>>+ self.INITRD_OFFSET, self.INITRD_SIZE)
>>+ self.extract(self.image_path, self.dtb_path,
>>+ self.DTB_OFFSET, self.DTB_SIZE)
>>+
>>+ def test_aarch64_imx8mm_evk_usdhc(self):
>>+ self.require_accelerator("tcg")
>>+ self.set_machine('imx8mm-evk')
>>+ self.vm.set_console(console_index=1)
>>+ self.vm.add_args('-m', '2G',
>>+ '-smp', '4',
>>+ '-kernel', self.kernel_path,
>>+ '-initrd', self.initrd_path,
>>+ '-dtb', self.dtb_path,
>>+ '-append', 'root=/dev/mmcblk2p1',
>>+ '-drive', f'file={self.image_path},if=sd,bus=2,'
>>+
>>+ 'format=raw,id=mmcblk2,snapshot=on')
>>+
>>+ self.vm.launch()
>>+ self.wait_for_console_pattern('Welcome to ')
>>+
>>+if __name__ == '__main__':
>>+ LinuxKernelTest.main()
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
2025-11-11 23:44 ` Bernhard Beschow
@ 2025-11-13 10:52 ` Gaurav Sharma
2025-11-17 13:14 ` Bernhard Beschow
0 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-13 10:52 UTC (permalink / raw)
To: Bernhard Beschow, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
"s/Plus/Mini/ ?"
-- Typo. Will fix it in v2
"`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc "
-- Okay got it. Will remove the KVM Acceleration section from the rst doc in v2
" Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful."
-- honestly, I have a fairly limited knowledge on the subject but this is what I know about the wake up logic at the silicon level:-
Timer IRQ → GIC-500 → GPC → Power Domain Controller → CPU Wake
After receiving the IRQ, GIC distributor logic sends a wake signal to the GPC if the cpu is sleeping. GPC manages power domains for each CPU, that means using some configuration registers it can decide which cpu will handle the wake request. In the GPC, the system mode controller will be responsible to power up the A53 core, which then sends the request to the PGTSC(power gating controller) to wake up the cpu. Debugging in the GPC implementation and checking if it is receiveing signal from GIC might help your cause.
--
-----Original Message-----
From: Bernhard Beschow <shentey@gmail.com>
Sent: 12 November 2025 05:14
To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
[You don't often get email from shentey@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Am 10. November 2025 11:22:45 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>Implemented CPUs, RAM, UARTs and Interrupt Controller Other peripherals
>are represented as TYPE_UNIMPLEMENTED_DEVICE Complete memory map of the
>SoC is provided.
>
>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>---
> docs/system/arm/imx8mm-evk.rst | 70 +++++++
> docs/system/target-arm.rst | 1 +
> hw/arm/Kconfig | 12 ++
> hw/arm/fsl-imx8mm.c | 363 +++++++++++++++++++++++++++++++++
> hw/arm/imx8mm-evk.c | 107 ++++++++++
> hw/arm/meson.build | 2 +
> include/hw/arm/fsl-imx8mm.h | 156 ++++++++++++++
> 7 files changed, 711 insertions(+)
> create mode 100644 docs/system/arm/imx8mm-evk.rst create mode 100644
>hw/arm/fsl-imx8mm.c create mode 100644 hw/arm/imx8mm-evk.c create
>mode 100644 include/hw/arm/fsl-imx8mm.h
>
>diff --git a/docs/system/arm/imx8mm-evk.rst
>b/docs/system/arm/imx8mm-evk.rst new file mode 100644 index
>0000000000..61d28ebf72
>--- /dev/null
>+++ b/docs/system/arm/imx8mm-evk.rst
>@@ -0,0 +1,70 @@
>+NXP i.MX 8MM Evaluation Kit (``imx8mm-evk``)
>+================================================
>+
>+The ``imx8mm-evk`` machine models the i.MX 8M Plus Evaluation Kit,
>+based on an
s/Plus/Mini/ ?
>+i.MX 8MM SoC.
>+
>+Supported devices
>+-----------------
>+
>+The ``imx8mm-evk`` machine implements the following devices:
>+
>+ * Up to 4 Cortex-A53 cores
>+ * Generic Interrupt Controller (GICv3)
>+ * 4 UARTs
>+
>+Boot options
>+------------
>+
>+The ``imx8mm-evk`` machine can start a Linux kernel directly using the
>+standard ``-kernel`` functionality.
>+
>+Direct Linux Kernel Boot
>+''''''''''''''''''''''''
>+
>+Probably the easiest way to get started with a whole Linux system on
>+the machine is to generate an image with Buildroot. Version 2024.11.1
>+is tested at the time of writing and involves two steps. First run the
>+following commands in the toplevel directory of the Buildroot source tree:
>+
>+.. code-block:: bash
>+
>+ $ make freescale_imx8mmevk_defconfig $ make
>+
>+Once finished successfully there is an ``output/image`` subfolder.
>+Navigate into it and resize the SD card image to a power of two:
>+
>+.. code-block:: bash
>+
>+ $ qemu-img resize sdcard.img 256M
>+
>+Now that everything is prepared the machine can be started as follows:
>+
>+.. code-block:: bash
>+
>+ $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 3G \
>+ -display none -serial null -serial stdio \
>+ -kernel Image \
>+ -dtb imx8mm-evk.dtb \
>+ -append "root=/dev/mmcblk2p2" \
>+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>+
>+
>+KVM Acceleration
>+----------------
>+
>+To enable hardware-assisted acceleration via KVM, append ``-accel kvm
>+-cpu host`` to the command line. While this speeds up performance
`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc.
>+significantly, be aware of the following limitations:
>+
>+* The ``imx8mm-evk`` machine is not included under the "virtualization use case"
>+ of :doc:`QEMU's security policy </system/security>`. This means that
>+you
>+ should not trust that it can contain malicious guests, whether it is
>+run
>+ using TCG or KVM. If you don't trust your guests and you're relying
>+on QEMU to
>+ be the security boundary, you want to choose another machine such as ``virt``.
>+* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
>+ This is a limitation of KVM and may not work with guests with a
>+tight
>+ dependency on Cortex-A53.
>+* No EL2 and EL3 exception levels are available which is also a KVM limitation.
>+ Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.
>diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
>index a96d1867df..d6a4b5bb00 100644
>--- a/docs/system/target-arm.rst
>+++ b/docs/system/target-arm.rst
>@@ -97,6 +97,7 @@ Board-specific documentation
> arm/mcimx6ul-evk
> arm/mcimx7d-sabre
> arm/imx8mp-evk
>+ arm/imx8mm-evk
> arm/orangepi
> arm/raspi
> arm/collie
>diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
>0cdeb60f1f..7c66f3c3cd 100644
>--- a/hw/arm/Kconfig
>+++ b/hw/arm/Kconfig
>@@ -626,6 +626,18 @@ config FSL_IMX8MP_EVK
> depends on TCG || KVM
> select FSL_IMX8MP
>
>+config FSL_IMX8MM
>+ bool
>+ select ARM_GIC
>+ select IMX
>+
>+config FSL_IMX8MM_EVK
>+ bool
>+ default y
>+ depends on AARCH64
>+ depends on TCG || KVM
>+ select FSL_IMX8MM
>+
> config ARM_SMMUV3
> bool
>
>diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c new file mode
>100644 index 0000000000..9c8acc1e99
>--- /dev/null
>+++ b/hw/arm/fsl-imx8mm.c
>@@ -0,0 +1,363 @@
>+/*
>+ * i.MX 8MM SoC Implementation
>+ *
>+ * Based on hw/arm/fsl-imx6.c
>+ *
>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>+
>+#include "qemu/osdep.h"
>+#include "system/address-spaces.h"
>+#include "hw/arm/bsa.h"
>+#include "hw/arm/fsl-imx8mm.h"
>+#include "hw/misc/unimp.h"
>+#include "hw/boards.h"
>+#include "system/kvm.h"
>+#include "system/system.h"
>+#include "target/arm/cpu.h"
>+#include "target/arm/cpu-qom.h"
>+#include "target/arm/kvm_arm.h"
>+#include "qapi/error.h"
>+#include "qobject/qlist.h"
>+
>+static const struct {
>+ hwaddr addr;
>+ size_t size;
>+ const char *name;
>+} fsl_imx8mm_memmap[] = {
>+ [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
>+ [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
>+ [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
>+ [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
>+ [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
>+ [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
>+ [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
>+ [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
>+ [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
>+ [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
>+ [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
>+ [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
>+ [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
>+ [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
>+ [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
>+ [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
>+ [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
>+ [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
>+ [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
>+ [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
>+
>+ /* AIPS-4 Begin */
>+ [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
>+ [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
>+ [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
>+ [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
>+ [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
>+ [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
>+ [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
>+ /* AIPS-4 End */
>+
>+ [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect"
>+ },
>+
>+ /* AIPS-3 Begin */
>+ [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
>+ [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
>+ [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
>+ [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
>+ [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
>+ [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
>+ [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
>+ [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
>+ [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
>+ [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
>+ [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
>+ [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
>+ [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
>+ [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
>+ [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
>+ [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
>+ [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
>+ [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
>+ [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
>+ [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
>+ [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
>+ [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
>+ [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
>+ /* AIPS-3 End */
>+
>+ /* AIPS-2 Begin */
>+ [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
>+ [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
>+ [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
>+ [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
>+ [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
>+ [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
>+ [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
>+ [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
>+ [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
>+ [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
>+ [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
>+ [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
>+ [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
>+ [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
>+ /* AIPS-2 End */
>+
>+ /* AIPS-1 Begin */
>+ [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
>+ [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
>+ [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
>+ [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
>+ [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
>+ [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
>+ [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
>+ [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
>+ [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
>+ [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
>+ [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
>+ [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
>+ [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
>+ [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
>+ [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
>+ [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
>+ [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
>+ [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
>+ [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
>+ [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
>+ [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
>+ [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
>+ [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
>+ [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
>+ [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
>+ [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
>+ [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
>+ [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
>+ [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
>+ [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
>+ [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
>+ [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
>+ [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
>+
>+ /* AIPS-1 End */
>+
>+ [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
>+ [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
>+ [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
>+ [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
>+ [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
>+ [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
>+ [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
>+ [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
>+ [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
>+ [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" }, };
>+
>+static void fsl_imx8mm_init(Object *obj) {
>+ MachineState *ms = MACHINE(qdev_get_machine());
>+ FslImx8mmState *s = FSL_IMX8MM(obj);
>+ const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
>+ int i;
>+
>+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
>+ g_autofree char *name = g_strdup_printf("cpu%d", i);
>+ object_initialize_child(obj, name, &s->cpu[i], cpu_type);
>+ }
>+
>+ object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
>+
>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
>+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>+ }
>+
>+}
>+
>+static void fsl_imx8mm_realize(DeviceState *dev, Error **errp) {
>+ MachineState *ms = MACHINE(qdev_get_machine());
>+ FslImx8mmState *s = FSL_IMX8MM(dev);
>+ DeviceState *gicdev = DEVICE(&s->gic);
>+ int i;
>+
>+ if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
>+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>+ TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
>+ return;
>+ }
>+
>+ /* CPUs */
>+ for (i = 0; i < ms->smp.cpus; i++) {
>+ /* On uniprocessor, the CBAR is set to 0 */
>+ if (ms->smp.cpus > 1 &&
>+ object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
>+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
>+ &error_abort);
>+ }
>+
>+ /*
>+ * CNTFID0 base frequency in Hz of system counter
>+ */
>+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>+ &error_abort);
>+
>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
>+ !kvm_enabled(), &error_abort);
>+ }
>+
>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
>+ !kvm_enabled(), &error_abort);
>+ }
>+
>+ if (i) {
>+ /*
>+ * Secondary CPUs start in powered-down state (and can be
>+ * powered up via the SRC system reset controller)
>+ */
>+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
>+ true, &error_abort);
>+ }
>+
>+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
>+ return;
>+ }
>+ }
>+
>+ /* GIC */
>+ {
>+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
>+ QList *redist_region_count;
>+ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu",
>+ NULL);
>+
>+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
>+ qdev_prop_set_uint32(gicdev, "num-irq",
>+ FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
>+ redist_region_count = qlist_new();
>+ qlist_append_int(redist_region_count, ms->smp.cpus);
>+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
>+ object_property_set_link(OBJECT(&s->gic), "sysmem",
>+ OBJECT(get_system_memory()), &error_fatal);
>+ if (!sysbus_realize(gicsbd, errp)) {
>+ return;
>+ }
>+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
>+ sysbus_mmio_map(gicsbd, 1,
>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
>+
>+ /*
>+ * Wire the outputs from each CPU's generic timer and the GICv3
>+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
>+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
>+ */
>+ for (i = 0; i < ms->smp.cpus; i++) {
>+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
>+ int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
>+ qemu_irq irq;
>+
>+ /*
>+ * Mapping from the output timer irq lines from the CPU to the
>+ * GIC PPI inputs.
>+ */
>+ static const int timer_irqs[] = {
>+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
>+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
>+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
>+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
>+ };
>+
>+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
>+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
>+ qdev_connect_gpio_out(cpudev, j, irq);
>+ }
>+
>+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
>+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
>+ 0, irq);
>+
>+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
>+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
>+ irq);
>+
>+ sysbus_connect_irq(gicsbd, i,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
>+ sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
>+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
>+ sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
>+ qdev_get_gpio_in(cpudev,
>+ ARM_CPU_VFIQ));
>+
>+ if (kvm_enabled()) {
>+ if (pmu) {
>+ assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
>+ if (kvm_irqchip_in_kernel()) {
>+ kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
>+ }
>+ kvm_arm_pmu_init(&s->cpu[i]);
>+ }
>+ }
>+ }
>+ }
>+
>+ /* UARTs */
>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>+ struct {
>+ hwaddr addr;
>+ unsigned int irq;
>+ } serial_table[FSL_IMX8MM_NUM_UARTS] = {
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
>+ };
>+
>+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
>+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
>+ return;
>+ }
>+
>+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
>+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
>+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
>+ }
>+
>+ /* Unimplemented devices */
>+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
>+ switch (i) {
>+ case FSL_IMX8MM_GIC_DIST:
>+ case FSL_IMX8MM_GIC_REDIST:
>+ case FSL_IMX8MM_RAM:
>+ case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
>+ /* device implemented and treated above */
>+ break;
>+
>+ default:
>+ create_unimplemented_device(fsl_imx8mm_memmap[i].name,
>+ fsl_imx8mm_memmap[i].addr,
>+ fsl_imx8mm_memmap[i].size);
>+ break;
>+ }
>+ }
>+}
>+
>+static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data) {
>+ DeviceClass *dc = DEVICE_CLASS(oc);
>+
>+ dc->realize = fsl_imx8mm_realize;
>+
>+ dc->desc = "i.MX 8MM SoC";
>+}
>+
>+static const TypeInfo fsl_imx8mm_types[] = {
>+ {
>+ .name = TYPE_FSL_IMX8MM,
>+ .parent = TYPE_SYS_BUS_DEVICE,
>+ .instance_size = sizeof(FslImx8mmState),
>+ .instance_init = fsl_imx8mm_init,
>+ .class_init = fsl_imx8mm_class_init,
>+ },
>+};
>+
>+DEFINE_TYPES(fsl_imx8mm_types)
>diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c new file mode
>100644 index 0000000000..cfb42fe464
>--- /dev/null
>+++ b/hw/arm/imx8mm-evk.c
>@@ -0,0 +1,107 @@
>+/*
>+ * NXP i.MX 8MM Evaluation Kit System Emulation
>+ *
>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>+
>+#include "qemu/osdep.h"
>+#include "system/address-spaces.h"
>+#include "hw/arm/boot.h"
>+#include "hw/arm/fsl-imx8mm.h"
>+#include "hw/arm/machines-qom.h"
>+#include "hw/boards.h"
>+#include "hw/qdev-properties.h"
>+#include "system/kvm.h"
>+#include "system/qtest.h"
>+#include "qemu/error-report.h"
>+#include "qapi/error.h"
>+#include <libfdt.h>
>+
>+static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info,
>+void *fdt) {
>+ int i, offset;
>+
>+ /* Temporarily disable following nodes until they are implemented */
>+ const char *nodes_to_remove[] = {
>+ "nxp,imx8mm-fspi",
>+ };
>+
>+ for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
>+ const char *dev_str = nodes_to_remove[i];
>+
>+ offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
>+ while (offset >= 0) {
>+ fdt_nop_node(fdt, offset);
>+ offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
>+ }
>+ }
>+
>+ /* Remove cpu-idle-states property from CPU nodes */
>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
>+ while (offset >= 0) {
>+ fdt_nop_property(fdt, offset, "cpu-idle-states");
>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
>+ }
Removing the idle-states ptoperties is only needed since the CPU goes into deep sleep mode during boot and is unable to wake up, even with an imx_sysctr implementation <https://github.com/shentok/qemu/blob/imx8mp/hw/timer/imx_sysctr.c>. Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful.
Thanks,
Bernhard
>+
>+ if (kvm_enabled()) {
>+ /* Use system counter frequency from host CPU to fix time in guest */
>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
>+ while (offset >= 0) {
>+ fdt_nop_property(fdt, offset, "clock-frequency");
>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
>+ }
>+ }
>+}
>+
>+static void imx8mm_evk_init(MachineState *machine) {
>+ static struct arm_boot_info boot_info;
>+ FslImx8mmState *s;
>+
>+ if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
>+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
>+ machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
>+ exit(1);
>+ }
>+
>+ boot_info = (struct arm_boot_info) {
>+ .loader_start = FSL_IMX8MM_RAM_START,
>+ .board_id = -1,
>+ .ram_size = machine->ram_size,
>+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
>+ .modify_dtb = imx8mm_evk_modify_dtb,
>+ };
>+
>+ s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
>+ 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_IMX8MM_RAM_START,
>+ machine->ram);
>+
>+ if (!qtest_enabled()) {
>+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
>+ }
>+}
>+
>+static const char *imx8mm_evk_get_default_cpu_type(const MachineState
>+*ms) {
>+ if (kvm_enabled()) {
>+ return ARM_CPU_TYPE_NAME("host");
>+ }
>+
>+ return ARM_CPU_TYPE_NAME("cortex-a53"); }
>+
>+static void imx8mm_evk_machine_init(MachineClass *mc) {
>+ mc->desc = "NXP i.MX 8MM EVK Board";
>+ mc->init = imx8mm_evk_init;
>+ mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
>+ mc->default_ram_id = "imx8mm-evk.ram";
>+ mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type; }
>+
>+DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
>diff --git a/hw/arm/meson.build b/hw/arm/meson.build index
>aeaf654790..12ecb824cc 100644
>--- a/hw/arm/meson.build
>+++ b/hw/arm/meson.build
>@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true:
>files('armsse.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true:
>files('fsl-imx7.c', 'mcimx7d-sabre.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true:
>files('fsl-imx8mp.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true:
>files('imx8mp-evk.c'))
>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true:
>+files('fsl-imx8mm.c'))
>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true:
>+files('imx8mm-evk.c'))
> arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true:
>files('smmuv3.c'))
> arm_common_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true:
>files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
> arm_common_ss.add(when: 'CONFIG_NRF51_SOC', if_true:
>files('nrf51_soc.c')) diff --git a/include/hw/arm/fsl-imx8mm.h
>b/include/hw/arm/fsl-imx8mm.h new file mode 100644 index
>0000000000..aa954ea00b
>--- /dev/null
>+++ b/include/hw/arm/fsl-imx8mm.h
>@@ -0,0 +1,156 @@
>+/*
>+ * i.MX 8MM SoC Definitions
>+ *
>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>+
>+#ifndef FSL_IMX8MM_H
>+#define FSL_IMX8MM_H
>+
>+#include "cpu.h"
>+#include "hw/char/imx_serial.h"
>+#include "hw/intc/arm_gicv3_common.h"
>+#include "qom/object.h"
>+#include "qemu/units.h"
>+
>+#define TYPE_FSL_IMX8MM "fsl-imx8mm"
>+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
>+
>+#define FSL_IMX8MM_RAM_START 0x40000000
>+#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
>+
>+enum FslImx8mmConfiguration {
>+ FSL_IMX8MM_NUM_CPUS = 4,
>+ FSL_IMX8MM_NUM_IRQS = 128,
>+ FSL_IMX8MM_NUM_UARTS = 4,
>+};
>+
>+struct FslImx8mmState {
>+ SysBusDevice parent_obj;
>+
>+ ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
>+ GICv3State gic;
>+ IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
>+};
>+
>+enum FslImx8mmMemoryRegions {
>+ FSL_IMX8MM_A53_DAP,
>+ FSL_IMX8MM_AIPS1_CONFIGURATION,
>+ FSL_IMX8MM_AIPS2_CONFIGURATION,
>+ FSL_IMX8MM_AIPS3_CONFIGURATION,
>+ FSL_IMX8MM_AIPS4_CONFIGURATION,
>+ FSL_IMX8MM_ANA_OSC,
>+ FSL_IMX8MM_ANA_PLL,
>+ FSL_IMX8MM_ANA_TSENSOR,
>+ FSL_IMX8MM_APBH_DMA,
>+ FSL_IMX8MM_BOOT_ROM,
>+ FSL_IMX8MM_BOOT_ROM_PROTECTED,
>+ FSL_IMX8MM_CAAM,
>+ FSL_IMX8MM_CAAM_MEM,
>+ FSL_IMX8MM_CCM,
>+ FSL_IMX8MM_CSU,
>+ FSL_IMX8MM_DDR_CTL,
>+ FSL_IMX8MM_DDR_PERF_MON,
>+ FSL_IMX8MM_DDR_PHY,
>+ FSL_IMX8MM_DDR_PHY_BROADCAST,
>+ FSL_IMX8MM_ECSPI1,
>+ FSL_IMX8MM_ECSPI2,
>+ FSL_IMX8MM_ECSPI3,
>+ FSL_IMX8MM_ENET1,
>+ FSL_IMX8MM_GIC_DIST,
>+ FSL_IMX8MM_GIC_REDIST,
>+ FSL_IMX8MM_GPC,
>+ FSL_IMX8MM_GPIO1,
>+ FSL_IMX8MM_GPIO2,
>+ FSL_IMX8MM_GPIO3,
>+ FSL_IMX8MM_GPIO4,
>+ FSL_IMX8MM_GPIO5,
>+ FSL_IMX8MM_GPT1,
>+ FSL_IMX8MM_GPT2,
>+ FSL_IMX8MM_GPT3,
>+ FSL_IMX8MM_GPT4,
>+ FSL_IMX8MM_GPT5,
>+ FSL_IMX8MM_GPT6,
>+ FSL_IMX8MM_GPU2D,
>+ FSL_IMX8MM_I2C1,
>+ FSL_IMX8MM_I2C2,
>+ FSL_IMX8MM_I2C3,
>+ FSL_IMX8MM_I2C4,
>+ FSL_IMX8MM_INTERCONNECT,
>+ FSL_IMX8MM_IOMUXC,
>+ FSL_IMX8MM_IOMUXC_GPR,
>+ FSL_IMX8MM_MEDIA_BLK_CTL,
>+ FSL_IMX8MM_LCDIF,
>+ FSL_IMX8MM_MIPI_CSI,
>+ FSL_IMX8MM_MIPI_DSI,
>+ FSL_IMX8MM_MU_A,
>+ FSL_IMX8MM_MU_B,
>+ FSL_IMX8MM_OCOTP_CTRL,
>+ FSL_IMX8MM_OCRAM,
>+ FSL_IMX8MM_OCRAM_S,
>+ FSL_IMX8MM_PCIE1,
>+ FSL_IMX8MM_PCIE1_MEM,
>+ FSL_IMX8MM_PCIE_PHY1,
>+ FSL_IMX8MM_PERFMON1,
>+ FSL_IMX8MM_PERFMON2,
>+ FSL_IMX8MM_PWM1,
>+ FSL_IMX8MM_PWM2,
>+ FSL_IMX8MM_PWM3,
>+ FSL_IMX8MM_PWM4,
>+ FSL_IMX8MM_QOSC,
>+ FSL_IMX8MM_QSPI,
>+ FSL_IMX8MM_QSPI1_RX_BUFFER,
>+ FSL_IMX8MM_QSPI1_TX_BUFFER,
>+ FSL_IMX8MM_QSPI_MEM,
>+ FSL_IMX8MM_RAM,
>+ FSL_IMX8MM_RDC,
>+ FSL_IMX8MM_SAI1,
>+ FSL_IMX8MM_SAI2,
>+ FSL_IMX8MM_SAI3,
>+ FSL_IMX8MM_SAI5,
>+ FSL_IMX8MM_SAI6,
>+ FSL_IMX8MM_SDMA1,
>+ FSL_IMX8MM_SDMA2,
>+ FSL_IMX8MM_SDMA3,
>+ FSL_IMX8MM_SEMAPHORE1,
>+ FSL_IMX8MM_SEMAPHORE2,
>+ FSL_IMX8MM_SEMAPHORE_HS,
>+ FSL_IMX8MM_SNVS_HP,
>+ FSL_IMX8MM_SPBA1,
>+ FSL_IMX8MM_SRC,
>+ FSL_IMX8MM_SYSCNT_CMP,
>+ FSL_IMX8MM_SYSCNT_CTRL,
>+ FSL_IMX8MM_SYSCNT_RD,
>+ FSL_IMX8MM_TCM_DTCM,
>+ FSL_IMX8MM_TCM_ITCM,
>+ FSL_IMX8MM_TZASC,
>+ FSL_IMX8MM_UART1,
>+ FSL_IMX8MM_UART2,
>+ FSL_IMX8MM_UART3,
>+ FSL_IMX8MM_UART4,
>+ FSL_IMX8MM_USB1,
>+ FSL_IMX8MM_USB2,
>+ FSL_IMX8MM_USB1_OTG,
>+ FSL_IMX8MM_USB2_OTG,
>+ FSL_IMX8MM_USDHC1,
>+ FSL_IMX8MM_USDHC2,
>+ FSL_IMX8MM_USDHC3,
>+ FSL_IMX8MM_VPU,
>+ FSL_IMX8MM_VPU_BLK_CTRL,
>+ FSL_IMX8MM_VPU_G1_DECODER,
>+ FSL_IMX8MM_VPU_G2_DECODER,
>+ FSL_IMX8MM_WDOG1,
>+ FSL_IMX8MM_WDOG2,
>+ FSL_IMX8MM_WDOG3,
>+};
>+
>+enum FslImx8mmIrqs {
>+ FSL_IMX8MM_UART1_IRQ = 26,
>+ FSL_IMX8MM_UART2_IRQ = 27,
>+ FSL_IMX8MM_UART3_IRQ = 28,
>+ FSL_IMX8MM_UART4_IRQ = 29,
>+};
>+
>+#endif /* FSL_IMX8MM_H */
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
2025-11-13 10:52 ` [EXT] " Gaurav Sharma
@ 2025-11-17 13:14 ` Bernhard Beschow
2025-11-18 5:26 ` Gaurav Sharma
0 siblings, 1 reply; 34+ messages in thread
From: Bernhard Beschow @ 2025-11-17 13:14 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Am 13. November 2025 10:52:54 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>"s/Plus/Mini/ ?"
>
>-- Typo. Will fix it in v2
>
>"`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc "
>
>-- Okay got it. Will remove the KVM Acceleration section from the rst doc in v2
No need to remove the whole section. Since the machine supports KVM this section should be there. It's just that the "-cpu host" is redundant in "-accel kvm -cpu host".
>
>" Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful."
>
>-- honestly, I have a fairly limited knowledge on the subject but this is what I know about the wake up logic at the silicon level:-
>
>Timer IRQ → GIC-500 → GPC → Power Domain Controller → CPU Wake
>After receiving the IRQ, GIC distributor logic sends a wake signal to the GPC if the cpu is sleeping. GPC manages power domains for each CPU, that means using some configuration registers it can decide which cpu will handle the wake request. In the GPC, the system mode controller will be responsible to power up the A53 core, which then sends the request to the PGTSC(power gating controller) to wake up the cpu. Debugging in the GPC implementation and checking if it is receiveing signal from GIC might help your cause.
Thanks, now I think I see what is going on. The guest configures for wakeup by GIC and deactivates all IRQs before shutting down the CPU, so it doesn't get confused when waking up. When the wakeup IRQ arrives, it actually becomes pending, but then QEMU needs to wake the CPU by executing the wakeup path in the guest which will enable interrupts again and thus serve the pending IRQ. That part in QEMU is not yet implemented which is why we need to remove the DTB properties.
Best regards,
Bernhard
>
>
>--
>-----Original Message-----
>From: Bernhard Beschow <shentey@gmail.com>
>Sent: 12 November 2025 05:14
>To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
>
>[You don't often get email from shentey@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
>Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
>
>
>Am 10. November 2025 11:22:45 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>>Implemented CPUs, RAM, UARTs and Interrupt Controller Other peripherals
>>are represented as TYPE_UNIMPLEMENTED_DEVICE Complete memory map of the
>>SoC is provided.
>>
>>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>---
>> docs/system/arm/imx8mm-evk.rst | 70 +++++++
>> docs/system/target-arm.rst | 1 +
>> hw/arm/Kconfig | 12 ++
>> hw/arm/fsl-imx8mm.c | 363 +++++++++++++++++++++++++++++++++
>> hw/arm/imx8mm-evk.c | 107 ++++++++++
>> hw/arm/meson.build | 2 +
>> include/hw/arm/fsl-imx8mm.h | 156 ++++++++++++++
>> 7 files changed, 711 insertions(+)
>> create mode 100644 docs/system/arm/imx8mm-evk.rst create mode 100644
>>hw/arm/fsl-imx8mm.c create mode 100644 hw/arm/imx8mm-evk.c create
>>mode 100644 include/hw/arm/fsl-imx8mm.h
>>
>>diff --git a/docs/system/arm/imx8mm-evk.rst
>>b/docs/system/arm/imx8mm-evk.rst new file mode 100644 index
>>0000000000..61d28ebf72
>>--- /dev/null
>>+++ b/docs/system/arm/imx8mm-evk.rst
>>@@ -0,0 +1,70 @@
>>+NXP i.MX 8MM Evaluation Kit (``imx8mm-evk``)
>>+================================================
>>+
>>+The ``imx8mm-evk`` machine models the i.MX 8M Plus Evaluation Kit,
>>+based on an
>
>s/Plus/Mini/ ?
>
>>+i.MX 8MM SoC.
>>+
>>+Supported devices
>>+-----------------
>>+
>>+The ``imx8mm-evk`` machine implements the following devices:
>>+
>>+ * Up to 4 Cortex-A53 cores
>>+ * Generic Interrupt Controller (GICv3)
>>+ * 4 UARTs
>>+
>>+Boot options
>>+------------
>>+
>>+The ``imx8mm-evk`` machine can start a Linux kernel directly using the
>>+standard ``-kernel`` functionality.
>>+
>>+Direct Linux Kernel Boot
>>+''''''''''''''''''''''''
>>+
>>+Probably the easiest way to get started with a whole Linux system on
>>+the machine is to generate an image with Buildroot. Version 2024.11.1
>>+is tested at the time of writing and involves two steps. First run the
>>+following commands in the toplevel directory of the Buildroot source tree:
>>+
>>+.. code-block:: bash
>>+
>>+ $ make freescale_imx8mmevk_defconfig $ make
>>+
>>+Once finished successfully there is an ``output/image`` subfolder.
>>+Navigate into it and resize the SD card image to a power of two:
>>+
>>+.. code-block:: bash
>>+
>>+ $ qemu-img resize sdcard.img 256M
>>+
>>+Now that everything is prepared the machine can be started as follows:
>>+
>>+.. code-block:: bash
>>+
>>+ $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 3G \
>>+ -display none -serial null -serial stdio \
>>+ -kernel Image \
>>+ -dtb imx8mm-evk.dtb \
>>+ -append "root=/dev/mmcblk2p2" \
>>+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>>+
>>+
>>+KVM Acceleration
>>+----------------
>>+
>>+To enable hardware-assisted acceleration via KVM, append ``-accel kvm
>>+-cpu host`` to the command line. While this speeds up performance
>
>`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc.
>
>>+significantly, be aware of the following limitations:
>>+
>>+* The ``imx8mm-evk`` machine is not included under the "virtualization use case"
>>+ of :doc:`QEMU's security policy </system/security>`. This means that
>>+you
>>+ should not trust that it can contain malicious guests, whether it is
>>+run
>>+ using TCG or KVM. If you don't trust your guests and you're relying
>>+on QEMU to
>>+ be the security boundary, you want to choose another machine such as ``virt``.
>>+* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
>>+ This is a limitation of KVM and may not work with guests with a
>>+tight
>>+ dependency on Cortex-A53.
>>+* No EL2 and EL3 exception levels are available which is also a KVM limitation.
>>+ Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.
>>diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
>>index a96d1867df..d6a4b5bb00 100644
>>--- a/docs/system/target-arm.rst
>>+++ b/docs/system/target-arm.rst
>>@@ -97,6 +97,7 @@ Board-specific documentation
>> arm/mcimx6ul-evk
>> arm/mcimx7d-sabre
>> arm/imx8mp-evk
>>+ arm/imx8mm-evk
>> arm/orangepi
>> arm/raspi
>> arm/collie
>>diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
>>0cdeb60f1f..7c66f3c3cd 100644
>>--- a/hw/arm/Kconfig
>>+++ b/hw/arm/Kconfig
>>@@ -626,6 +626,18 @@ config FSL_IMX8MP_EVK
>> depends on TCG || KVM
>> select FSL_IMX8MP
>>
>>+config FSL_IMX8MM
>>+ bool
>>+ select ARM_GIC
>>+ select IMX
>>+
>>+config FSL_IMX8MM_EVK
>>+ bool
>>+ default y
>>+ depends on AARCH64
>>+ depends on TCG || KVM
>>+ select FSL_IMX8MM
>>+
>> config ARM_SMMUV3
>> bool
>>
>>diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c new file mode
>>100644 index 0000000000..9c8acc1e99
>>--- /dev/null
>>+++ b/hw/arm/fsl-imx8mm.c
>>@@ -0,0 +1,363 @@
>>+/*
>>+ * i.MX 8MM SoC Implementation
>>+ *
>>+ * Based on hw/arm/fsl-imx6.c
>>+ *
>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>+ *
>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>+
>>+#include "qemu/osdep.h"
>>+#include "system/address-spaces.h"
>>+#include "hw/arm/bsa.h"
>>+#include "hw/arm/fsl-imx8mm.h"
>>+#include "hw/misc/unimp.h"
>>+#include "hw/boards.h"
>>+#include "system/kvm.h"
>>+#include "system/system.h"
>>+#include "target/arm/cpu.h"
>>+#include "target/arm/cpu-qom.h"
>>+#include "target/arm/kvm_arm.h"
>>+#include "qapi/error.h"
>>+#include "qobject/qlist.h"
>>+
>>+static const struct {
>>+ hwaddr addr;
>>+ size_t size;
>>+ const char *name;
>>+} fsl_imx8mm_memmap[] = {
>>+ [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
>>+ [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
>>+ [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
>>+ [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
>>+ [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
>>+ [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
>>+ [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
>>+ [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
>>+ [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
>>+ [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
>>+ [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
>>+ [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
>>+ [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
>>+ [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
>>+ [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
>>+ [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
>>+ [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
>>+ [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
>>+ [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
>>+ [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
>>+
>>+ /* AIPS-4 Begin */
>>+ [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
>>+ [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
>>+ [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
>>+ [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
>>+ [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
>>+ [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
>>+ [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
>>+ /* AIPS-4 End */
>>+
>>+ [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect"
>>+ },
>>+
>>+ /* AIPS-3 Begin */
>>+ [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
>>+ [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
>>+ [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
>>+ [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
>>+ [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
>>+ [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
>>+ [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
>>+ [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
>>+ [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
>>+ [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
>>+ [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
>>+ [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
>>+ [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
>>+ [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
>>+ [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
>>+ [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
>>+ [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
>>+ [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
>>+ [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
>>+ [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
>>+ [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
>>+ [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
>>+ [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
>>+ /* AIPS-3 End */
>>+
>>+ /* AIPS-2 Begin */
>>+ [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
>>+ [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
>>+ [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
>>+ [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
>>+ [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
>>+ [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
>>+ [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
>>+ [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
>>+ [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
>>+ [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
>>+ [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
>>+ [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
>>+ [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
>>+ [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
>>+ /* AIPS-2 End */
>>+
>>+ /* AIPS-1 Begin */
>>+ [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
>>+ [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
>>+ [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
>>+ [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
>>+ [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
>>+ [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
>>+ [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
>>+ [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
>>+ [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
>>+ [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
>>+ [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
>>+ [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
>>+ [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
>>+ [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
>>+ [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
>>+ [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
>>+ [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
>>+ [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
>>+ [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
>>+ [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
>>+ [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
>>+ [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
>>+ [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
>>+ [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
>>+ [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
>>+ [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
>>+ [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
>>+ [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
>>+ [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
>>+ [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
>>+ [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
>>+ [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
>>+ [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
>>+
>>+ /* AIPS-1 End */
>>+
>>+ [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
>>+ [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
>>+ [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
>>+ [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
>>+ [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
>>+ [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
>>+ [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
>>+ [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
>>+ [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
>>+ [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" }, };
>>+
>>+static void fsl_imx8mm_init(Object *obj) {
>>+ MachineState *ms = MACHINE(qdev_get_machine());
>>+ FslImx8mmState *s = FSL_IMX8MM(obj);
>>+ const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
>>+ int i;
>>+
>>+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
>>+ g_autofree char *name = g_strdup_printf("cpu%d", i);
>>+ object_initialize_child(obj, name, &s->cpu[i], cpu_type);
>>+ }
>>+
>>+ object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
>>+
>>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>>+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
>>+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>>+ }
>>+
>>+}
>>+
>>+static void fsl_imx8mm_realize(DeviceState *dev, Error **errp) {
>>+ MachineState *ms = MACHINE(qdev_get_machine());
>>+ FslImx8mmState *s = FSL_IMX8MM(dev);
>>+ DeviceState *gicdev = DEVICE(&s->gic);
>>+ int i;
>>+
>>+ if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
>>+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>>+ TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
>>+ return;
>>+ }
>>+
>>+ /* CPUs */
>>+ for (i = 0; i < ms->smp.cpus; i++) {
>>+ /* On uniprocessor, the CBAR is set to 0 */
>>+ if (ms->smp.cpus > 1 &&
>>+ object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
>>+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
>>+ &error_abort);
>>+ }
>>+
>>+ /*
>>+ * CNTFID0 base frequency in Hz of system counter
>>+ */
>>+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>>+ &error_abort);
>>+
>>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
>>+ !kvm_enabled(), &error_abort);
>>+ }
>>+
>>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
>>+ !kvm_enabled(), &error_abort);
>>+ }
>>+
>>+ if (i) {
>>+ /*
>>+ * Secondary CPUs start in powered-down state (and can be
>>+ * powered up via the SRC system reset controller)
>>+ */
>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
>>+ true, &error_abort);
>>+ }
>>+
>>+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
>>+ return;
>>+ }
>>+ }
>>+
>>+ /* GIC */
>>+ {
>>+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
>>+ QList *redist_region_count;
>>+ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu",
>>+ NULL);
>>+
>>+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
>>+ qdev_prop_set_uint32(gicdev, "num-irq",
>>+ FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
>>+ redist_region_count = qlist_new();
>>+ qlist_append_int(redist_region_count, ms->smp.cpus);
>>+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
>>+ object_property_set_link(OBJECT(&s->gic), "sysmem",
>>+ OBJECT(get_system_memory()), &error_fatal);
>>+ if (!sysbus_realize(gicsbd, errp)) {
>>+ return;
>>+ }
>>+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
>>+ sysbus_mmio_map(gicsbd, 1,
>>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
>>+
>>+ /*
>>+ * Wire the outputs from each CPU's generic timer and the GICv3
>>+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
>>+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
>>+ */
>>+ for (i = 0; i < ms->smp.cpus; i++) {
>>+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
>>+ int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
>>+ qemu_irq irq;
>>+
>>+ /*
>>+ * Mapping from the output timer irq lines from the CPU to the
>>+ * GIC PPI inputs.
>>+ */
>>+ static const int timer_irqs[] = {
>>+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
>>+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
>>+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
>>+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
>>+ };
>>+
>>+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
>>+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
>>+ qdev_connect_gpio_out(cpudev, j, irq);
>>+ }
>>+
>>+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
>>+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
>>+ 0, irq);
>>+
>>+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
>>+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
>>+ irq);
>>+
>>+ sysbus_connect_irq(gicsbd, i,
>>+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>>+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
>>+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
>>+ sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
>>+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
>>+ sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
>>+ qdev_get_gpio_in(cpudev,
>>+ ARM_CPU_VFIQ));
>>+
>>+ if (kvm_enabled()) {
>>+ if (pmu) {
>>+ assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
>>+ if (kvm_irqchip_in_kernel()) {
>>+ kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
>>+ }
>>+ kvm_arm_pmu_init(&s->cpu[i]);
>>+ }
>>+ }
>>+ }
>>+ }
>>+
>>+ /* UARTs */
>>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>>+ struct {
>>+ hwaddr addr;
>>+ unsigned int irq;
>>+ } serial_table[FSL_IMX8MM_NUM_UARTS] = {
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
>>+ };
>>+
>>+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
>>+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
>>+ return;
>>+ }
>>+
>>+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
>>+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
>>+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
>>+ }
>>+
>>+ /* Unimplemented devices */
>>+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
>>+ switch (i) {
>>+ case FSL_IMX8MM_GIC_DIST:
>>+ case FSL_IMX8MM_GIC_REDIST:
>>+ case FSL_IMX8MM_RAM:
>>+ case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
>>+ /* device implemented and treated above */
>>+ break;
>>+
>>+ default:
>>+ create_unimplemented_device(fsl_imx8mm_memmap[i].name,
>>+ fsl_imx8mm_memmap[i].addr,
>>+ fsl_imx8mm_memmap[i].size);
>>+ break;
>>+ }
>>+ }
>>+}
>>+
>>+static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data) {
>>+ DeviceClass *dc = DEVICE_CLASS(oc);
>>+
>>+ dc->realize = fsl_imx8mm_realize;
>>+
>>+ dc->desc = "i.MX 8MM SoC";
>>+}
>>+
>>+static const TypeInfo fsl_imx8mm_types[] = {
>>+ {
>>+ .name = TYPE_FSL_IMX8MM,
>>+ .parent = TYPE_SYS_BUS_DEVICE,
>>+ .instance_size = sizeof(FslImx8mmState),
>>+ .instance_init = fsl_imx8mm_init,
>>+ .class_init = fsl_imx8mm_class_init,
>>+ },
>>+};
>>+
>>+DEFINE_TYPES(fsl_imx8mm_types)
>>diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c new file mode
>>100644 index 0000000000..cfb42fe464
>>--- /dev/null
>>+++ b/hw/arm/imx8mm-evk.c
>>@@ -0,0 +1,107 @@
>>+/*
>>+ * NXP i.MX 8MM Evaluation Kit System Emulation
>>+ *
>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>+ *
>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>+
>>+#include "qemu/osdep.h"
>>+#include "system/address-spaces.h"
>>+#include "hw/arm/boot.h"
>>+#include "hw/arm/fsl-imx8mm.h"
>>+#include "hw/arm/machines-qom.h"
>>+#include "hw/boards.h"
>>+#include "hw/qdev-properties.h"
>>+#include "system/kvm.h"
>>+#include "system/qtest.h"
>>+#include "qemu/error-report.h"
>>+#include "qapi/error.h"
>>+#include <libfdt.h>
>>+
>>+static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info,
>>+void *fdt) {
>>+ int i, offset;
>>+
>>+ /* Temporarily disable following nodes until they are implemented */
>>+ const char *nodes_to_remove[] = {
>>+ "nxp,imx8mm-fspi",
>>+ };
>>+
>>+ for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
>>+ const char *dev_str = nodes_to_remove[i];
>>+
>>+ offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
>>+ while (offset >= 0) {
>>+ fdt_nop_node(fdt, offset);
>>+ offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
>>+ }
>>+ }
>>+
>>+ /* Remove cpu-idle-states property from CPU nodes */
>>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
>>+ while (offset >= 0) {
>>+ fdt_nop_property(fdt, offset, "cpu-idle-states");
>>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
>>+ }
>
>Removing the idle-states ptoperties is only needed since the CPU goes into deep sleep mode during boot and is unable to wake up, even with an imx_sysctr implementation <https://github.com/shentok/qemu/blob/imx8mp/hw/timer/imx_sysctr.c>. Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful.
>
>Thanks,
>Bernhard
>
>>+
>>+ if (kvm_enabled()) {
>>+ /* Use system counter frequency from host CPU to fix time in guest */
>>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
>>+ while (offset >= 0) {
>>+ fdt_nop_property(fdt, offset, "clock-frequency");
>>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
>>+ }
>>+ }
>>+}
>>+
>>+static void imx8mm_evk_init(MachineState *machine) {
>>+ static struct arm_boot_info boot_info;
>>+ FslImx8mmState *s;
>>+
>>+ if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
>>+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
>>+ machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
>>+ exit(1);
>>+ }
>>+
>>+ boot_info = (struct arm_boot_info) {
>>+ .loader_start = FSL_IMX8MM_RAM_START,
>>+ .board_id = -1,
>>+ .ram_size = machine->ram_size,
>>+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
>>+ .modify_dtb = imx8mm_evk_modify_dtb,
>>+ };
>>+
>>+ s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
>>+ 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_IMX8MM_RAM_START,
>>+ machine->ram);
>>+
>>+ if (!qtest_enabled()) {
>>+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
>>+ }
>>+}
>>+
>>+static const char *imx8mm_evk_get_default_cpu_type(const MachineState
>>+*ms) {
>>+ if (kvm_enabled()) {
>>+ return ARM_CPU_TYPE_NAME("host");
>>+ }
>>+
>>+ return ARM_CPU_TYPE_NAME("cortex-a53"); }
>>+
>>+static void imx8mm_evk_machine_init(MachineClass *mc) {
>>+ mc->desc = "NXP i.MX 8MM EVK Board";
>>+ mc->init = imx8mm_evk_init;
>>+ mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
>>+ mc->default_ram_id = "imx8mm-evk.ram";
>>+ mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type; }
>>+
>>+DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
>>diff --git a/hw/arm/meson.build b/hw/arm/meson.build index
>>aeaf654790..12ecb824cc 100644
>>--- a/hw/arm/meson.build
>>+++ b/hw/arm/meson.build
>>@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true:
>>files('armsse.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true:
>>files('fsl-imx7.c', 'mcimx7d-sabre.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true:
>>files('fsl-imx8mp.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true:
>>files('imx8mp-evk.c'))
>>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true:
>>+files('fsl-imx8mm.c'))
>>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true:
>>+files('imx8mm-evk.c'))
>> arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true:
>>files('smmuv3.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true:
>>files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
>> arm_common_ss.add(when: 'CONFIG_NRF51_SOC', if_true:
>>files('nrf51_soc.c')) diff --git a/include/hw/arm/fsl-imx8mm.h
>>b/include/hw/arm/fsl-imx8mm.h new file mode 100644 index
>>0000000000..aa954ea00b
>>--- /dev/null
>>+++ b/include/hw/arm/fsl-imx8mm.h
>>@@ -0,0 +1,156 @@
>>+/*
>>+ * i.MX 8MM SoC Definitions
>>+ *
>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>+ *
>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>+
>>+#ifndef FSL_IMX8MM_H
>>+#define FSL_IMX8MM_H
>>+
>>+#include "cpu.h"
>>+#include "hw/char/imx_serial.h"
>>+#include "hw/intc/arm_gicv3_common.h"
>>+#include "qom/object.h"
>>+#include "qemu/units.h"
>>+
>>+#define TYPE_FSL_IMX8MM "fsl-imx8mm"
>>+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
>>+
>>+#define FSL_IMX8MM_RAM_START 0x40000000
>>+#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
>>+
>>+enum FslImx8mmConfiguration {
>>+ FSL_IMX8MM_NUM_CPUS = 4,
>>+ FSL_IMX8MM_NUM_IRQS = 128,
>>+ FSL_IMX8MM_NUM_UARTS = 4,
>>+};
>>+
>>+struct FslImx8mmState {
>>+ SysBusDevice parent_obj;
>>+
>>+ ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
>>+ GICv3State gic;
>>+ IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
>>+};
>>+
>>+enum FslImx8mmMemoryRegions {
>>+ FSL_IMX8MM_A53_DAP,
>>+ FSL_IMX8MM_AIPS1_CONFIGURATION,
>>+ FSL_IMX8MM_AIPS2_CONFIGURATION,
>>+ FSL_IMX8MM_AIPS3_CONFIGURATION,
>>+ FSL_IMX8MM_AIPS4_CONFIGURATION,
>>+ FSL_IMX8MM_ANA_OSC,
>>+ FSL_IMX8MM_ANA_PLL,
>>+ FSL_IMX8MM_ANA_TSENSOR,
>>+ FSL_IMX8MM_APBH_DMA,
>>+ FSL_IMX8MM_BOOT_ROM,
>>+ FSL_IMX8MM_BOOT_ROM_PROTECTED,
>>+ FSL_IMX8MM_CAAM,
>>+ FSL_IMX8MM_CAAM_MEM,
>>+ FSL_IMX8MM_CCM,
>>+ FSL_IMX8MM_CSU,
>>+ FSL_IMX8MM_DDR_CTL,
>>+ FSL_IMX8MM_DDR_PERF_MON,
>>+ FSL_IMX8MM_DDR_PHY,
>>+ FSL_IMX8MM_DDR_PHY_BROADCAST,
>>+ FSL_IMX8MM_ECSPI1,
>>+ FSL_IMX8MM_ECSPI2,
>>+ FSL_IMX8MM_ECSPI3,
>>+ FSL_IMX8MM_ENET1,
>>+ FSL_IMX8MM_GIC_DIST,
>>+ FSL_IMX8MM_GIC_REDIST,
>>+ FSL_IMX8MM_GPC,
>>+ FSL_IMX8MM_GPIO1,
>>+ FSL_IMX8MM_GPIO2,
>>+ FSL_IMX8MM_GPIO3,
>>+ FSL_IMX8MM_GPIO4,
>>+ FSL_IMX8MM_GPIO5,
>>+ FSL_IMX8MM_GPT1,
>>+ FSL_IMX8MM_GPT2,
>>+ FSL_IMX8MM_GPT3,
>>+ FSL_IMX8MM_GPT4,
>>+ FSL_IMX8MM_GPT5,
>>+ FSL_IMX8MM_GPT6,
>>+ FSL_IMX8MM_GPU2D,
>>+ FSL_IMX8MM_I2C1,
>>+ FSL_IMX8MM_I2C2,
>>+ FSL_IMX8MM_I2C3,
>>+ FSL_IMX8MM_I2C4,
>>+ FSL_IMX8MM_INTERCONNECT,
>>+ FSL_IMX8MM_IOMUXC,
>>+ FSL_IMX8MM_IOMUXC_GPR,
>>+ FSL_IMX8MM_MEDIA_BLK_CTL,
>>+ FSL_IMX8MM_LCDIF,
>>+ FSL_IMX8MM_MIPI_CSI,
>>+ FSL_IMX8MM_MIPI_DSI,
>>+ FSL_IMX8MM_MU_A,
>>+ FSL_IMX8MM_MU_B,
>>+ FSL_IMX8MM_OCOTP_CTRL,
>>+ FSL_IMX8MM_OCRAM,
>>+ FSL_IMX8MM_OCRAM_S,
>>+ FSL_IMX8MM_PCIE1,
>>+ FSL_IMX8MM_PCIE1_MEM,
>>+ FSL_IMX8MM_PCIE_PHY1,
>>+ FSL_IMX8MM_PERFMON1,
>>+ FSL_IMX8MM_PERFMON2,
>>+ FSL_IMX8MM_PWM1,
>>+ FSL_IMX8MM_PWM2,
>>+ FSL_IMX8MM_PWM3,
>>+ FSL_IMX8MM_PWM4,
>>+ FSL_IMX8MM_QOSC,
>>+ FSL_IMX8MM_QSPI,
>>+ FSL_IMX8MM_QSPI1_RX_BUFFER,
>>+ FSL_IMX8MM_QSPI1_TX_BUFFER,
>>+ FSL_IMX8MM_QSPI_MEM,
>>+ FSL_IMX8MM_RAM,
>>+ FSL_IMX8MM_RDC,
>>+ FSL_IMX8MM_SAI1,
>>+ FSL_IMX8MM_SAI2,
>>+ FSL_IMX8MM_SAI3,
>>+ FSL_IMX8MM_SAI5,
>>+ FSL_IMX8MM_SAI6,
>>+ FSL_IMX8MM_SDMA1,
>>+ FSL_IMX8MM_SDMA2,
>>+ FSL_IMX8MM_SDMA3,
>>+ FSL_IMX8MM_SEMAPHORE1,
>>+ FSL_IMX8MM_SEMAPHORE2,
>>+ FSL_IMX8MM_SEMAPHORE_HS,
>>+ FSL_IMX8MM_SNVS_HP,
>>+ FSL_IMX8MM_SPBA1,
>>+ FSL_IMX8MM_SRC,
>>+ FSL_IMX8MM_SYSCNT_CMP,
>>+ FSL_IMX8MM_SYSCNT_CTRL,
>>+ FSL_IMX8MM_SYSCNT_
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
2025-11-17 13:14 ` Bernhard Beschow
@ 2025-11-18 5:26 ` Gaurav Sharma
2025-11-18 9:46 ` Bernhard Beschow
0 siblings, 1 reply; 34+ messages in thread
From: Gaurav Sharma @ 2025-11-18 5:26 UTC (permalink / raw)
To: Bernhard Beschow, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
" No need to remove the whole section. Since the machine supports KVM this section should be there. It's just that the "-cpu host" is redundant in "-accel kvm -cpu host"
-- does that mean that every ARM machine enabled so far inside hw/arm/ except 'virt' is not supported for a virtualization use-case in qemu?
-----Original Message-----
From: Bernhard Beschow <shentey@gmail.com>
Sent: 17 November 2025 18:45
To: Gaurav Sharma <gaurav.sharma_7@nxp.com>; qemu-devel@nongnu.org
Cc: pbonzini@redhat.com; peter.maydell@linaro.org
Subject: RE: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
Am 13. November 2025 10:52:54 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>"s/Plus/Mini/ ?"
>
>-- Typo. Will fix it in v2
>
>"`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc "
>
>-- Okay got it. Will remove the KVM Acceleration section from the rst
>doc in v2
No need to remove the whole section. Since the machine supports KVM this section should be there. It's just that the "-cpu host" is redundant in "-accel kvm -cpu host".
>
>" Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful."
>
>-- honestly, I have a fairly limited knowledge on the subject but this
>is what I know about the wake up logic at the silicon level:-
>
>Timer IRQ → GIC-500 → GPC → Power Domain Controller → CPU Wake After
>receiving the IRQ, GIC distributor logic sends a wake signal to the GPC if the cpu is sleeping. GPC manages power domains for each CPU, that means using some configuration registers it can decide which cpu will handle the wake request. In the GPC, the system mode controller will be responsible to power up the A53 core, which then sends the request to the PGTSC(power gating controller) to wake up the cpu. Debugging in the GPC implementation and checking if it is receiveing signal from GIC might help your cause.
Thanks, now I think I see what is going on. The guest configures for wakeup by GIC and deactivates all IRQs before shutting down the CPU, so it doesn't get confused when waking up. When the wakeup IRQ arrives, it actually becomes pending, but then QEMU needs to wake the CPU by executing the wakeup path in the guest which will enable interrupts again and thus serve the pending IRQ. That part in QEMU is not yet implemented which is why we need to remove the DTB properties.
Best regards,
Bernhard
>
>
>--
>-----Original Message-----
>From: Bernhard Beschow <shentey@gmail.com>
>Sent: 12 November 2025 05:14
>To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM
>EVK(Evaluation Kit) board
>
>[You don't often get email from shentey@gmail.com. Learn why this is
>important at https://aka.ms/LearnAboutSenderIdentification ]
>
>Caution: This is an external email. Please take care when clicking
>links or opening attachments. When in doubt, report the message using
>the 'Report this email' button
>
>
>Am 10. November 2025 11:22:45 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>>Implemented CPUs, RAM, UARTs and Interrupt Controller Other
>>peripherals are represented as TYPE_UNIMPLEMENTED_DEVICE Complete
>>memory map of the SoC is provided.
>>
>>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>---
>> docs/system/arm/imx8mm-evk.rst | 70 +++++++
>> docs/system/target-arm.rst | 1 +
>> hw/arm/Kconfig | 12 ++
>> hw/arm/fsl-imx8mm.c | 363 +++++++++++++++++++++++++++++++++
>> hw/arm/imx8mm-evk.c | 107 ++++++++++
>> hw/arm/meson.build | 2 +
>> include/hw/arm/fsl-imx8mm.h | 156 ++++++++++++++
>> 7 files changed, 711 insertions(+)
>> create mode 100644 docs/system/arm/imx8mm-evk.rst create mode 100644
>>hw/arm/fsl-imx8mm.c create mode 100644 hw/arm/imx8mm-evk.c create
>>mode 100644 include/hw/arm/fsl-imx8mm.h
>>
>>diff --git a/docs/system/arm/imx8mm-evk.rst
>>b/docs/system/arm/imx8mm-evk.rst new file mode 100644 index
>>0000000000..61d28ebf72
>>--- /dev/null
>>+++ b/docs/system/arm/imx8mm-evk.rst
>>@@ -0,0 +1,70 @@
>>+NXP i.MX 8MM Evaluation Kit (``imx8mm-evk``)
>>+================================================
>>+
>>+The ``imx8mm-evk`` machine models the i.MX 8M Plus Evaluation Kit,
>>+based on an
>
>s/Plus/Mini/ ?
>
>>+i.MX 8MM SoC.
>>+
>>+Supported devices
>>+-----------------
>>+
>>+The ``imx8mm-evk`` machine implements the following devices:
>>+
>>+ * Up to 4 Cortex-A53 cores
>>+ * Generic Interrupt Controller (GICv3)
>>+ * 4 UARTs
>>+
>>+Boot options
>>+------------
>>+
>>+The ``imx8mm-evk`` machine can start a Linux kernel directly using
>>+the standard ``-kernel`` functionality.
>>+
>>+Direct Linux Kernel Boot
>>+''''''''''''''''''''''''
>>+
>>+Probably the easiest way to get started with a whole Linux system on
>>+the machine is to generate an image with Buildroot. Version 2024.11.1
>>+is tested at the time of writing and involves two steps. First run
>>+the following commands in the toplevel directory of the Buildroot source tree:
>>+
>>+.. code-block:: bash
>>+
>>+ $ make freescale_imx8mmevk_defconfig $ make
>>+
>>+Once finished successfully there is an ``output/image`` subfolder.
>>+Navigate into it and resize the SD card image to a power of two:
>>+
>>+.. code-block:: bash
>>+
>>+ $ qemu-img resize sdcard.img 256M
>>+
>>+Now that everything is prepared the machine can be started as follows:
>>+
>>+.. code-block:: bash
>>+
>>+ $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 3G \
>>+ -display none -serial null -serial stdio \
>>+ -kernel Image \
>>+ -dtb imx8mm-evk.dtb \
>>+ -append "root=/dev/mmcblk2p2" \
>>+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>>+
>>+
>>+KVM Acceleration
>>+----------------
>>+
>>+To enable hardware-assisted acceleration via KVM, append ``-accel kvm
>>+-cpu host`` to the command line. While this speeds up performance
>
>`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc.
>
>>+significantly, be aware of the following limitations:
>>+
>>+* The ``imx8mm-evk`` machine is not included under the "virtualization use case"
>>+ of :doc:`QEMU's security policy </system/security>`. This means
>>+that you
>>+ should not trust that it can contain malicious guests, whether it
>>+is run
>>+ using TCG or KVM. If you don't trust your guests and you're relying
>>+on QEMU to
>>+ be the security boundary, you want to choose another machine such as ``virt``.
>>+* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
>>+ This is a limitation of KVM and may not work with guests with a
>>+tight
>>+ dependency on Cortex-A53.
>>+* No EL2 and EL3 exception levels are available which is also a KVM limitation.
>>+ Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.
>>diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
>>index a96d1867df..d6a4b5bb00 100644
>>--- a/docs/system/target-arm.rst
>>+++ b/docs/system/target-arm.rst
>>@@ -97,6 +97,7 @@ Board-specific documentation
>> arm/mcimx6ul-evk
>> arm/mcimx7d-sabre
>> arm/imx8mp-evk
>>+ arm/imx8mm-evk
>> arm/orangepi
>> arm/raspi
>> arm/collie
>>diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
>>0cdeb60f1f..7c66f3c3cd 100644
>>--- a/hw/arm/Kconfig
>>+++ b/hw/arm/Kconfig
>>@@ -626,6 +626,18 @@ config FSL_IMX8MP_EVK
>> depends on TCG || KVM
>> select FSL_IMX8MP
>>
>>+config FSL_IMX8MM
>>+ bool
>>+ select ARM_GIC
>>+ select IMX
>>+
>>+config FSL_IMX8MM_EVK
>>+ bool
>>+ default y
>>+ depends on AARCH64
>>+ depends on TCG || KVM
>>+ select FSL_IMX8MM
>>+
>> config ARM_SMMUV3
>> bool
>>
>>diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c new file mode
>>100644 index 0000000000..9c8acc1e99
>>--- /dev/null
>>+++ b/hw/arm/fsl-imx8mm.c
>>@@ -0,0 +1,363 @@
>>+/*
>>+ * i.MX 8MM SoC Implementation
>>+ *
>>+ * Based on hw/arm/fsl-imx6.c
>>+ *
>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>+ *
>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>+
>>+#include "qemu/osdep.h"
>>+#include "system/address-spaces.h"
>>+#include "hw/arm/bsa.h"
>>+#include "hw/arm/fsl-imx8mm.h"
>>+#include "hw/misc/unimp.h"
>>+#include "hw/boards.h"
>>+#include "system/kvm.h"
>>+#include "system/system.h"
>>+#include "target/arm/cpu.h"
>>+#include "target/arm/cpu-qom.h"
>>+#include "target/arm/kvm_arm.h"
>>+#include "qapi/error.h"
>>+#include "qobject/qlist.h"
>>+
>>+static const struct {
>>+ hwaddr addr;
>>+ size_t size;
>>+ const char *name;
>>+} fsl_imx8mm_memmap[] = {
>>+ [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
>>+ [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
>>+ [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
>>+ [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
>>+ [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
>>+ [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
>>+ [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
>>+ [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
>>+ [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
>>+ [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
>>+ [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
>>+ [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
>>+ [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
>>+ [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
>>+ [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
>>+ [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
>>+ [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
>>+ [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
>>+ [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
>>+ [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
>>+
>>+ /* AIPS-4 Begin */
>>+ [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
>>+ [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
>>+ [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
>>+ [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
>>+ [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
>>+ [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
>>+ [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
>>+ /* AIPS-4 End */
>>+
>>+ [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect"
>>+ },
>>+
>>+ /* AIPS-3 Begin */
>>+ [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
>>+ [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
>>+ [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
>>+ [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
>>+ [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
>>+ [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
>>+ [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
>>+ [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
>>+ [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
>>+ [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
>>+ [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
>>+ [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
>>+ [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
>>+ [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
>>+ [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
>>+ [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
>>+ [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
>>+ [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
>>+ [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
>>+ [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
>>+ [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
>>+ [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
>>+ [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
>>+ /* AIPS-3 End */
>>+
>>+ /* AIPS-2 Begin */
>>+ [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
>>+ [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
>>+ [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
>>+ [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
>>+ [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
>>+ [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
>>+ [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
>>+ [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
>>+ [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
>>+ [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
>>+ [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
>>+ [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
>>+ [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
>>+ [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
>>+ /* AIPS-2 End */
>>+
>>+ /* AIPS-1 Begin */
>>+ [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
>>+ [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
>>+ [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
>>+ [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
>>+ [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
>>+ [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
>>+ [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
>>+ [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
>>+ [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
>>+ [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
>>+ [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
>>+ [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
>>+ [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
>>+ [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
>>+ [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
>>+ [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
>>+ [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
>>+ [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
>>+ [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
>>+ [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
>>+ [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
>>+ [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
>>+ [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
>>+ [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
>>+ [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
>>+ [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
>>+ [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
>>+ [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
>>+ [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
>>+ [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
>>+ [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
>>+ [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
>>+ [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
>>+
>>+ /* AIPS-1 End */
>>+
>>+ [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
>>+ [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
>>+ [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
>>+ [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
>>+ [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
>>+ [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
>>+ [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
>>+ [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
>>+ [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
>>+ [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" }, };
>>+
>>+static void fsl_imx8mm_init(Object *obj) {
>>+ MachineState *ms = MACHINE(qdev_get_machine());
>>+ FslImx8mmState *s = FSL_IMX8MM(obj);
>>+ const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
>>+ int i;
>>+
>>+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
>>+ g_autofree char *name = g_strdup_printf("cpu%d", i);
>>+ object_initialize_child(obj, name, &s->cpu[i], cpu_type);
>>+ }
>>+
>>+ object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
>>+
>>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>>+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
>>+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>>+ }
>>+
>>+}
>>+
>>+static void fsl_imx8mm_realize(DeviceState *dev, Error **errp) {
>>+ MachineState *ms = MACHINE(qdev_get_machine());
>>+ FslImx8mmState *s = FSL_IMX8MM(dev);
>>+ DeviceState *gicdev = DEVICE(&s->gic);
>>+ int i;
>>+
>>+ if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
>>+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>>+ TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
>>+ return;
>>+ }
>>+
>>+ /* CPUs */
>>+ for (i = 0; i < ms->smp.cpus; i++) {
>>+ /* On uniprocessor, the CBAR is set to 0 */
>>+ if (ms->smp.cpus > 1 &&
>>+ object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
>>+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
>>+ &error_abort);
>>+ }
>>+
>>+ /*
>>+ * CNTFID0 base frequency in Hz of system counter
>>+ */
>>+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>>+ &error_abort);
>>+
>>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
>>+ !kvm_enabled(), &error_abort);
>>+ }
>>+
>>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
>>+ !kvm_enabled(), &error_abort);
>>+ }
>>+
>>+ if (i) {
>>+ /*
>>+ * Secondary CPUs start in powered-down state (and can be
>>+ * powered up via the SRC system reset controller)
>>+ */
>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
>>+ true, &error_abort);
>>+ }
>>+
>>+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
>>+ return;
>>+ }
>>+ }
>>+
>>+ /* GIC */
>>+ {
>>+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
>>+ QList *redist_region_count;
>>+ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu",
>>+ NULL);
>>+
>>+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
>>+ qdev_prop_set_uint32(gicdev, "num-irq",
>>+ FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
>>+ redist_region_count = qlist_new();
>>+ qlist_append_int(redist_region_count, ms->smp.cpus);
>>+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
>>+ object_property_set_link(OBJECT(&s->gic), "sysmem",
>>+ OBJECT(get_system_memory()), &error_fatal);
>>+ if (!sysbus_realize(gicsbd, errp)) {
>>+ return;
>>+ }
>>+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
>>+ sysbus_mmio_map(gicsbd, 1,
>>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
>>+
>>+ /*
>>+ * Wire the outputs from each CPU's generic timer and the GICv3
>>+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
>>+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
>>+ */
>>+ for (i = 0; i < ms->smp.cpus; i++) {
>>+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
>>+ int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
>>+ qemu_irq irq;
>>+
>>+ /*
>>+ * Mapping from the output timer irq lines from the CPU to the
>>+ * GIC PPI inputs.
>>+ */
>>+ static const int timer_irqs[] = {
>>+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
>>+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
>>+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
>>+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
>>+ };
>>+
>>+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
>>+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
>>+ qdev_connect_gpio_out(cpudev, j, irq);
>>+ }
>>+
>>+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
>>+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
>>+ 0, irq);
>>+
>>+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
>>+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
>>+ irq);
>>+
>>+ sysbus_connect_irq(gicsbd, i,
>>+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>>+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
>>+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
>>+ sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
>>+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
>>+ sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
>>+ qdev_get_gpio_in(cpudev,
>>+ ARM_CPU_VFIQ));
>>+
>>+ if (kvm_enabled()) {
>>+ if (pmu) {
>>+ assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
>>+ if (kvm_irqchip_in_kernel()) {
>>+ kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
>>+ }
>>+ kvm_arm_pmu_init(&s->cpu[i]);
>>+ }
>>+ }
>>+ }
>>+ }
>>+
>>+ /* UARTs */
>>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>>+ struct {
>>+ hwaddr addr;
>>+ unsigned int irq;
>>+ } serial_table[FSL_IMX8MM_NUM_UARTS] = {
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
>>+ };
>>+
>>+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
>>+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
>>+ return;
>>+ }
>>+
>>+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
>>+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
>>+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
>>+ }
>>+
>>+ /* Unimplemented devices */
>>+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
>>+ switch (i) {
>>+ case FSL_IMX8MM_GIC_DIST:
>>+ case FSL_IMX8MM_GIC_REDIST:
>>+ case FSL_IMX8MM_RAM:
>>+ case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
>>+ /* device implemented and treated above */
>>+ break;
>>+
>>+ default:
>>+ create_unimplemented_device(fsl_imx8mm_memmap[i].name,
>>+ fsl_imx8mm_memmap[i].addr,
>>+ fsl_imx8mm_memmap[i].size);
>>+ break;
>>+ }
>>+ }
>>+}
>>+
>>+static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data) {
>>+ DeviceClass *dc = DEVICE_CLASS(oc);
>>+
>>+ dc->realize = fsl_imx8mm_realize;
>>+
>>+ dc->desc = "i.MX 8MM SoC";
>>+}
>>+
>>+static const TypeInfo fsl_imx8mm_types[] = {
>>+ {
>>+ .name = TYPE_FSL_IMX8MM,
>>+ .parent = TYPE_SYS_BUS_DEVICE,
>>+ .instance_size = sizeof(FslImx8mmState),
>>+ .instance_init = fsl_imx8mm_init,
>>+ .class_init = fsl_imx8mm_class_init,
>>+ },
>>+};
>>+
>>+DEFINE_TYPES(fsl_imx8mm_types)
>>diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c new file mode
>>100644 index 0000000000..cfb42fe464
>>--- /dev/null
>>+++ b/hw/arm/imx8mm-evk.c
>>@@ -0,0 +1,107 @@
>>+/*
>>+ * NXP i.MX 8MM Evaluation Kit System Emulation
>>+ *
>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>+ *
>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>+
>>+#include "qemu/osdep.h"
>>+#include "system/address-spaces.h"
>>+#include "hw/arm/boot.h"
>>+#include "hw/arm/fsl-imx8mm.h"
>>+#include "hw/arm/machines-qom.h"
>>+#include "hw/boards.h"
>>+#include "hw/qdev-properties.h"
>>+#include "system/kvm.h"
>>+#include "system/qtest.h"
>>+#include "qemu/error-report.h"
>>+#include "qapi/error.h"
>>+#include <libfdt.h>
>>+
>>+static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info,
>>+void *fdt) {
>>+ int i, offset;
>>+
>>+ /* Temporarily disable following nodes until they are implemented */
>>+ const char *nodes_to_remove[] = {
>>+ "nxp,imx8mm-fspi",
>>+ };
>>+
>>+ for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
>>+ const char *dev_str = nodes_to_remove[i];
>>+
>>+ offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
>>+ while (offset >= 0) {
>>+ fdt_nop_node(fdt, offset);
>>+ offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
>>+ }
>>+ }
>>+
>>+ /* Remove cpu-idle-states property from CPU nodes */
>>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
>>+ while (offset >= 0) {
>>+ fdt_nop_property(fdt, offset, "cpu-idle-states");
>>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
>>+ }
>
>Removing the idle-states ptoperties is only needed since the CPU goes into deep sleep mode during boot and is unable to wake up, even with an imx_sysctr implementation <https://github.com/shentok/qemu/blob/imx8mp/hw/timer/imx_sysctr.c>. Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful.
>
>Thanks,
>Bernhard
>
>>+
>>+ if (kvm_enabled()) {
>>+ /* Use system counter frequency from host CPU to fix time in guest */
>>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
>>+ while (offset >= 0) {
>>+ fdt_nop_property(fdt, offset, "clock-frequency");
>>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
>>+ }
>>+ }
>>+}
>>+
>>+static void imx8mm_evk_init(MachineState *machine) {
>>+ static struct arm_boot_info boot_info;
>>+ FslImx8mmState *s;
>>+
>>+ if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
>>+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
>>+ machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
>>+ exit(1);
>>+ }
>>+
>>+ boot_info = (struct arm_boot_info) {
>>+ .loader_start = FSL_IMX8MM_RAM_START,
>>+ .board_id = -1,
>>+ .ram_size = machine->ram_size,
>>+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
>>+ .modify_dtb = imx8mm_evk_modify_dtb,
>>+ };
>>+
>>+ s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
>>+ 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_IMX8MM_RAM_START,
>>+ machine->ram);
>>+
>>+ if (!qtest_enabled()) {
>>+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
>>+ }
>>+}
>>+
>>+static const char *imx8mm_evk_get_default_cpu_type(const MachineState
>>+*ms) {
>>+ if (kvm_enabled()) {
>>+ return ARM_CPU_TYPE_NAME("host");
>>+ }
>>+
>>+ return ARM_CPU_TYPE_NAME("cortex-a53"); }
>>+
>>+static void imx8mm_evk_machine_init(MachineClass *mc) {
>>+ mc->desc = "NXP i.MX 8MM EVK Board";
>>+ mc->init = imx8mm_evk_init;
>>+ mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
>>+ mc->default_ram_id = "imx8mm-evk.ram";
>>+ mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type; }
>>+
>>+DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
>>diff --git a/hw/arm/meson.build b/hw/arm/meson.build index
>>aeaf654790..12ecb824cc 100644
>>--- a/hw/arm/meson.build
>>+++ b/hw/arm/meson.build
>>@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true:
>>files('armsse.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true:
>>files('fsl-imx7.c', 'mcimx7d-sabre.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true:
>>files('fsl-imx8mp.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true:
>>files('imx8mp-evk.c'))
>>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true:
>>+files('fsl-imx8mm.c'))
>>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true:
>>+files('imx8mm-evk.c'))
>> arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true:
>>files('smmuv3.c'))
>> arm_common_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true:
>>files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
>> arm_common_ss.add(when: 'CONFIG_NRF51_SOC', if_true:
>>files('nrf51_soc.c')) diff --git a/include/hw/arm/fsl-imx8mm.h
>>b/include/hw/arm/fsl-imx8mm.h new file mode 100644 index
>>0000000000..aa954ea00b
>>--- /dev/null
>>+++ b/include/hw/arm/fsl-imx8mm.h
>>@@ -0,0 +1,156 @@
>>+/*
>>+ * i.MX 8MM SoC Definitions
>>+ *
>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>+ *
>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>+
>>+#ifndef FSL_IMX8MM_H
>>+#define FSL_IMX8MM_H
>>+
>>+#include "cpu.h"
>>+#include "hw/char/imx_serial.h"
>>+#include "hw/intc/arm_gicv3_common.h"
>>+#include "qom/object.h"
>>+#include "qemu/units.h"
>>+
>>+#define TYPE_FSL_IMX8MM "fsl-imx8mm"
>>+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
>>+
>>+#define FSL_IMX8MM_RAM_START 0x40000000
>>+#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
>>+
>>+enum FslImx8mmConfiguration {
>>+ FSL_IMX8MM_NUM_CPUS = 4,
>>+ FSL_IMX8MM_NUM_IRQS = 128,
>>+ FSL_IMX8MM_NUM_UARTS = 4,
>>+};
>>+
>>+struct FslImx8mmState {
>>+ SysBusDevice parent_obj;
>>+
>>+ ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
>>+ GICv3State gic;
>>+ IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
>>+};
>>+
>>+enum FslImx8mmMemoryRegions {
>>+ FSL_IMX8MM_A53_DAP,
>>+ FSL_IMX8MM_AIPS1_CONFIGURATION,
>>+ FSL_IMX8MM_AIPS2_CONFIGURATION,
>>+ FSL_IMX8MM_AIPS3_CONFIGURATION,
>>+ FSL_IMX8MM_AIPS4_CONFIGURATION,
>>+ FSL_IMX8MM_ANA_OSC,
>>+ FSL_IMX8MM_ANA_PLL,
>>+ FSL_IMX8MM_ANA_TSENSOR,
>>+ FSL_IMX8MM_APBH_DMA,
>>+ FSL_IMX8MM_BOOT_ROM,
>>+ FSL_IMX8MM_BOOT_ROM_PROTECTED,
>>+ FSL_IMX8MM_CAAM,
>>+ FSL_IMX8MM_CAAM_MEM,
>>+ FSL_IMX8MM_CCM,
>>+ FSL_IMX8MM_CSU,
>>+ FSL_IMX8MM_DDR_CTL,
>>+ FSL_IMX8MM_DDR_PERF_MON,
>>+ FSL_IMX8MM_DDR_PHY,
>>+ FSL_IMX8MM_DDR_PHY_BROADCAST,
>>+ FSL_IMX8MM_ECSPI1,
>>+ FSL_IMX8MM_ECSPI2,
>>+ FSL_IMX8MM_ECSPI3,
>>+ FSL_IMX8MM_ENET1,
>>+ FSL_IMX8MM_GIC_DIST,
>>+ FSL_IMX8MM_GIC_REDIST,
>>+ FSL_IMX8MM_GPC,
>>+ FSL_IMX8MM_GPIO1,
>>+ FSL_IMX8MM_GPIO2,
>>+ FSL_IMX8MM_GPIO3,
>>+ FSL_IMX8MM_GPIO4,
>>+ FSL_IMX8MM_GPIO5,
>>+ FSL_IMX8MM_GPT1,
>>+ FSL_IMX8MM_GPT2,
>>+ FSL_IMX8MM_GPT3,
>>+ FSL_IMX8MM_GPT4,
>>+ FSL_IMX8MM_GPT5,
>>+ FSL_IMX8MM_GPT6,
>>+ FSL_IMX8MM_GPU2D,
>>+ FSL_IMX8MM_I2C1,
>>+ FSL_IMX8MM_I2C2,
>>+ FSL_IMX8MM_I2C3,
>>+ FSL_IMX8MM_I2C4,
>>+ FSL_IMX8MM_INTERCONNECT,
>>+ FSL_IMX8MM_IOMUXC,
>>+ FSL_IMX8MM_IOMUXC_GPR,
>>+ FSL_IMX8MM_MEDIA_BLK_CTL,
>>+ FSL_IMX8MM_LCDIF,
>>+ FSL_IMX8MM_MIPI_CSI,
>>+ FSL_IMX8MM_MIPI_DSI,
>>+ FSL_IMX8MM_MU_A,
>>+ FSL_IMX8MM_MU_B,
>>+ FSL_IMX8MM_OCOTP_CTRL,
>>+ FSL_IMX8MM_OCRAM,
>>+ FSL_IMX8MM_OCRAM_S,
>>+ FSL_IMX8MM_PCIE1,
>>+ FSL_IMX8MM_PCIE1_MEM,
>>+ FSL_IMX8MM_PCIE_PHY1,
>>+ FSL_IMX8MM_PERFMON1,
>>+ FSL_IMX8MM_PERFMON2,
>>+ FSL_IMX8MM_PWM1,
>>+ FSL_IMX8MM_PWM2,
>>+ FSL_IMX8MM_PWM3,
>>+ FSL_IMX8MM_PWM4,
>>+ FSL_IMX8MM_QOSC,
>>+ FSL_IMX8MM_QSPI,
>>+ FSL_IMX8MM_QSPI1_RX_BUFFER,
>>+ FSL_IMX8MM_QSPI1_TX_BUFFER,
>>+ FSL_IMX8MM_QSPI_MEM,
>>+ FSL_IMX8MM_RAM,
>>+ FSL_IMX8MM_RDC,
>>+ FSL_IMX8MM_SAI1,
>>+ FSL_IMX8MM_SAI2,
>>+ FSL_IMX8MM_SAI3,
>>+ FSL_IMX8MM_SAI5,
>>+ FSL_IMX8MM_SAI6,
>>+ FSL_IMX8MM_SDMA1,
>>+ FSL_IMX8MM_SDMA2,
>>+ FSL_IMX8MM_SDMA3,
>>+ FSL_IMX8MM_SEMAPHORE1,
>>+ FSL_IMX8MM_SEMAPHORE2,
>>+ FSL_IMX8MM_SEMAPHORE_HS,
>>+ FSL_IMX8MM_SNVS_HP,
>>+ FSL_IMX8MM_SPBA1,
>>+ FSL_IMX8MM_SRC,
>>+ FSL_IMX8MM_SYSCNT_CMP,
>>+ FSL_IMX8MM_SYSCNT_CTRL,
>>+ FSL_IMX8MM_SYSCNT_
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
2025-11-18 5:26 ` Gaurav Sharma
@ 2025-11-18 9:46 ` Bernhard Beschow
0 siblings, 0 replies; 34+ messages in thread
From: Bernhard Beschow @ 2025-11-18 9:46 UTC (permalink / raw)
To: Gaurav Sharma, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, peter.maydell@linaro.org
Am 18. November 2025 05:26:34 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>" No need to remove the whole section. Since the machine supports KVM this section should be there. It's just that the "-cpu host" is redundant in "-accel kvm -cpu host"
>
>-- does that mean that every ARM machine enabled so far inside hw/arm/ except 'virt' is not supported for a virtualization use-case in qemu?
Correct. See https://qemu.readthedocs.io/en/master/system/security.html .
>
>-----Original Message-----
>From: Bernhard Beschow <shentey@gmail.com>
>Sent: 17 November 2025 18:45
>To: Gaurav Sharma <gaurav.sharma_7@nxp.com>; qemu-devel@nongnu.org
>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>Subject: RE: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board
>
>Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
>
>
>Am 13. November 2025 10:52:54 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>>"s/Plus/Mini/ ?"
>>
>>-- Typo. Will fix it in v2
>>
>>"`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc "
>>
>>-- Okay got it. Will remove the KVM Acceleration section from the rst
>>doc in v2
>
>No need to remove the whole section. Since the machine supports KVM this section should be there. It's just that the "-cpu host" is redundant in "-accel kvm -cpu host".
>
>>
>>" Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful."
>>
>>-- honestly, I have a fairly limited knowledge on the subject but this
>>is what I know about the wake up logic at the silicon level:-
>>
>>Timer IRQ → GIC-500 → GPC → Power Domain Controller → CPU Wake After
>>receiving the IRQ, GIC distributor logic sends a wake signal to the GPC if the cpu is sleeping. GPC manages power domains for each CPU, that means using some configuration registers it can decide which cpu will handle the wake request. In the GPC, the system mode controller will be responsible to power up the A53 core, which then sends the request to the PGTSC(power gating controller) to wake up the cpu. Debugging in the GPC implementation and checking if it is receiveing signal from GIC might help your cause.
>
>Thanks, now I think I see what is going on. The guest configures for wakeup by GIC and deactivates all IRQs before shutting down the CPU, so it doesn't get confused when waking up. When the wakeup IRQ arrives, it actually becomes pending, but then QEMU needs to wake the CPU by executing the wakeup path in the guest which will enable interrupts again and thus serve the pending IRQ. That part in QEMU is not yet implemented which is why we need to remove the DTB properties.
>
>Best regards,
>Bernhard
>
>>
>>
>>--
>>-----Original Message-----
>>From: Bernhard Beschow <shentey@gmail.com>
>>Sent: 12 November 2025 05:14
>>To: qemu-devel@nongnu.org; Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>Cc: pbonzini@redhat.com; peter.maydell@linaro.org
>>Subject: [EXT] Re: [PATCH 01/13] hw/arm: Add the i.MX 8MM
>>EVK(Evaluation Kit) board
>>
>>[You don't often get email from shentey@gmail.com. Learn why this is
>>important at https://aka.ms/LearnAboutSenderIdentification ]
>>
>>Caution: This is an external email. Please take care when clicking
>>links or opening attachments. When in doubt, report the message using
>>the 'Report this email' button
>>
>>
>>Am 10. November 2025 11:22:45 UTC schrieb Gaurav Sharma <gaurav.sharma_7@nxp.com>:
>>>Implemented CPUs, RAM, UARTs and Interrupt Controller Other
>>>peripherals are represented as TYPE_UNIMPLEMENTED_DEVICE Complete
>>>memory map of the SoC is provided.
>>>
>>>Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>>---
>>> docs/system/arm/imx8mm-evk.rst | 70 +++++++
>>> docs/system/target-arm.rst | 1 +
>>> hw/arm/Kconfig | 12 ++
>>> hw/arm/fsl-imx8mm.c | 363 +++++++++++++++++++++++++++++++++
>>> hw/arm/imx8mm-evk.c | 107 ++++++++++
>>> hw/arm/meson.build | 2 +
>>> include/hw/arm/fsl-imx8mm.h | 156 ++++++++++++++
>>> 7 files changed, 711 insertions(+)
>>> create mode 100644 docs/system/arm/imx8mm-evk.rst create mode 100644
>>>hw/arm/fsl-imx8mm.c create mode 100644 hw/arm/imx8mm-evk.c create
>>>mode 100644 include/hw/arm/fsl-imx8mm.h
>>>
>>>diff --git a/docs/system/arm/imx8mm-evk.rst
>>>b/docs/system/arm/imx8mm-evk.rst new file mode 100644 index
>>>0000000000..61d28ebf72
>>>--- /dev/null
>>>+++ b/docs/system/arm/imx8mm-evk.rst
>>>@@ -0,0 +1,70 @@
>>>+NXP i.MX 8MM Evaluation Kit (``imx8mm-evk``)
>>>+================================================
>>>+
>>>+The ``imx8mm-evk`` machine models the i.MX 8M Plus Evaluation Kit,
>>>+based on an
>>
>>s/Plus/Mini/ ?
>>
>>>+i.MX 8MM SoC.
>>>+
>>>+Supported devices
>>>+-----------------
>>>+
>>>+The ``imx8mm-evk`` machine implements the following devices:
>>>+
>>>+ * Up to 4 Cortex-A53 cores
>>>+ * Generic Interrupt Controller (GICv3)
>>>+ * 4 UARTs
>>>+
>>>+Boot options
>>>+------------
>>>+
>>>+The ``imx8mm-evk`` machine can start a Linux kernel directly using
>>>+the standard ``-kernel`` functionality.
>>>+
>>>+Direct Linux Kernel Boot
>>>+''''''''''''''''''''''''
>>>+
>>>+Probably the easiest way to get started with a whole Linux system on
>>>+the machine is to generate an image with Buildroot. Version 2024.11.1
>>>+is tested at the time of writing and involves two steps. First run
>>>+the following commands in the toplevel directory of the Buildroot source tree:
>>>+
>>>+.. code-block:: bash
>>>+
>>>+ $ make freescale_imx8mmevk_defconfig $ make
>>>+
>>>+Once finished successfully there is an ``output/image`` subfolder.
>>>+Navigate into it and resize the SD card image to a power of two:
>>>+
>>>+.. code-block:: bash
>>>+
>>>+ $ qemu-img resize sdcard.img 256M
>>>+
>>>+Now that everything is prepared the machine can be started as follows:
>>>+
>>>+.. code-block:: bash
>>>+
>>>+ $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 3G \
>>>+ -display none -serial null -serial stdio \
>>>+ -kernel Image \
>>>+ -dtb imx8mm-evk.dtb \
>>>+ -append "root=/dev/mmcblk2p2" \
>>>+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
>>>+
>>>+
>>>+KVM Acceleration
>>>+----------------
>>>+
>>>+To enable hardware-assisted acceleration via KVM, append ``-accel kvm
>>>+-cpu host`` to the command line. While this speeds up performance
>>
>>`-cpu host` isn't actually needed since this is the default in KVM mode. We missed that nitpick in the imx8mp-evk doc.
>>
>>>+significantly, be aware of the following limitations:
>>>+
>>>+* The ``imx8mm-evk`` machine is not included under the "virtualization use case"
>>>+ of :doc:`QEMU's security policy </system/security>`. This means
>>>+that you
>>>+ should not trust that it can contain malicious guests, whether it
>>>+is run
>>>+ using TCG or KVM. If you don't trust your guests and you're relying
>>>+on QEMU to
>>>+ be the security boundary, you want to choose another machine such as ``virt``.
>>>+* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
>>>+ This is a limitation of KVM and may not work with guests with a
>>>+tight
>>>+ dependency on Cortex-A53.
>>>+* No EL2 and EL3 exception levels are available which is also a KVM limitation.
>>>+ Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.
>>>diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
>>>index a96d1867df..d6a4b5bb00 100644
>>>--- a/docs/system/target-arm.rst
>>>+++ b/docs/system/target-arm.rst
>>>@@ -97,6 +97,7 @@ Board-specific documentation
>>> arm/mcimx6ul-evk
>>> arm/mcimx7d-sabre
>>> arm/imx8mp-evk
>>>+ arm/imx8mm-evk
>>> arm/orangepi
>>> arm/raspi
>>> arm/collie
>>>diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index
>>>0cdeb60f1f..7c66f3c3cd 100644
>>>--- a/hw/arm/Kconfig
>>>+++ b/hw/arm/Kconfig
>>>@@ -626,6 +626,18 @@ config FSL_IMX8MP_EVK
>>> depends on TCG || KVM
>>> select FSL_IMX8MP
>>>
>>>+config FSL_IMX8MM
>>>+ bool
>>>+ select ARM_GIC
>>>+ select IMX
>>>+
>>>+config FSL_IMX8MM_EVK
>>>+ bool
>>>+ default y
>>>+ depends on AARCH64
>>>+ depends on TCG || KVM
>>>+ select FSL_IMX8MM
>>>+
>>> config ARM_SMMUV3
>>> bool
>>>
>>>diff --git a/hw/arm/fsl-imx8mm.c b/hw/arm/fsl-imx8mm.c new file mode
>>>100644 index 0000000000..9c8acc1e99
>>>--- /dev/null
>>>+++ b/hw/arm/fsl-imx8mm.c
>>>@@ -0,0 +1,363 @@
>>>+/*
>>>+ * i.MX 8MM SoC Implementation
>>>+ *
>>>+ * Based on hw/arm/fsl-imx6.c
>>>+ *
>>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>>+ *
>>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>>+
>>>+#include "qemu/osdep.h"
>>>+#include "system/address-spaces.h"
>>>+#include "hw/arm/bsa.h"
>>>+#include "hw/arm/fsl-imx8mm.h"
>>>+#include "hw/misc/unimp.h"
>>>+#include "hw/boards.h"
>>>+#include "system/kvm.h"
>>>+#include "system/system.h"
>>>+#include "target/arm/cpu.h"
>>>+#include "target/arm/cpu-qom.h"
>>>+#include "target/arm/kvm_arm.h"
>>>+#include "qapi/error.h"
>>>+#include "qobject/qlist.h"
>>>+
>>>+static const struct {
>>>+ hwaddr addr;
>>>+ size_t size;
>>>+ const char *name;
>>>+} fsl_imx8mm_memmap[] = {
>>>+ [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
>>>+ [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
>>>+ [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
>>>+ [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
>>>+ [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
>>>+ [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
>>>+ [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
>>>+ [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
>>>+ [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
>>>+ [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
>>>+ [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
>>>+ [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
>>>+ [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
>>>+ [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
>>>+ [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
>>>+ [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
>>>+ [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
>>>+ [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
>>>+ [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
>>>+ [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
>>>+
>>>+ /* AIPS-4 Begin */
>>>+ [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
>>>+ [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
>>>+ [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
>>>+ [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
>>>+ [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
>>>+ [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
>>>+ [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
>>>+ /* AIPS-4 End */
>>>+
>>>+ [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect"
>>>+ },
>>>+
>>>+ /* AIPS-3 Begin */
>>>+ [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
>>>+ [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
>>>+ [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
>>>+ [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
>>>+ [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
>>>+ [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
>>>+ [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
>>>+ [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
>>>+ [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
>>>+ [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
>>>+ [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
>>>+ [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
>>>+ [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
>>>+ [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
>>>+ [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
>>>+ [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
>>>+ [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
>>>+ [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
>>>+ [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
>>>+ [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
>>>+ [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
>>>+ [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
>>>+ [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
>>>+ /* AIPS-3 End */
>>>+
>>>+ /* AIPS-2 Begin */
>>>+ [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
>>>+ [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
>>>+ [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
>>>+ [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
>>>+ [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
>>>+ [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
>>>+ [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
>>>+ [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
>>>+ [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
>>>+ [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
>>>+ [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
>>>+ [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
>>>+ [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
>>>+ [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
>>>+ /* AIPS-2 End */
>>>+
>>>+ /* AIPS-1 Begin */
>>>+ [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
>>>+ [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
>>>+ [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
>>>+ [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
>>>+ [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
>>>+ [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
>>>+ [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
>>>+ [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
>>>+ [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
>>>+ [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
>>>+ [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
>>>+ [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
>>>+ [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
>>>+ [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
>>>+ [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
>>>+ [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
>>>+ [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
>>>+ [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
>>>+ [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
>>>+ [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
>>>+ [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
>>>+ [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
>>>+ [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
>>>+ [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
>>>+ [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
>>>+ [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
>>>+ [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
>>>+ [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
>>>+ [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
>>>+ [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
>>>+ [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
>>>+ [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
>>>+ [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
>>>+
>>>+ /* AIPS-1 End */
>>>+
>>>+ [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
>>>+ [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
>>>+ [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
>>>+ [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
>>>+ [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
>>>+ [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
>>>+ [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
>>>+ [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
>>>+ [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
>>>+ [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" }, };
>>>+
>>>+static void fsl_imx8mm_init(Object *obj) {
>>>+ MachineState *ms = MACHINE(qdev_get_machine());
>>>+ FslImx8mmState *s = FSL_IMX8MM(obj);
>>>+ const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
>>>+ int i;
>>>+
>>>+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
>>>+ g_autofree char *name = g_strdup_printf("cpu%d", i);
>>>+ object_initialize_child(obj, name, &s->cpu[i], cpu_type);
>>>+ }
>>>+
>>>+ object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
>>>+
>>>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>>>+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
>>>+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
>>>+ }
>>>+
>>>+}
>>>+
>>>+static void fsl_imx8mm_realize(DeviceState *dev, Error **errp) {
>>>+ MachineState *ms = MACHINE(qdev_get_machine());
>>>+ FslImx8mmState *s = FSL_IMX8MM(dev);
>>>+ DeviceState *gicdev = DEVICE(&s->gic);
>>>+ int i;
>>>+
>>>+ if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
>>>+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
>>>+ TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
>>>+ return;
>>>+ }
>>>+
>>>+ /* CPUs */
>>>+ for (i = 0; i < ms->smp.cpus; i++) {
>>>+ /* On uniprocessor, the CBAR is set to 0 */
>>>+ if (ms->smp.cpus > 1 &&
>>>+ object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
>>>+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
>>>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
>>>+ &error_abort);
>>>+ }
>>>+
>>>+ /*
>>>+ * CNTFID0 base frequency in Hz of system counter
>>>+ */
>>>+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
>>>+ &error_abort);
>>>+
>>>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
>>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
>>>+ !kvm_enabled(), &error_abort);
>>>+ }
>>>+
>>>+ if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
>>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
>>>+ !kvm_enabled(), &error_abort);
>>>+ }
>>>+
>>>+ if (i) {
>>>+ /*
>>>+ * Secondary CPUs start in powered-down state (and can be
>>>+ * powered up via the SRC system reset controller)
>>>+ */
>>>+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
>>>+ true, &error_abort);
>>>+ }
>>>+
>>>+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
>>>+ return;
>>>+ }
>>>+ }
>>>+
>>>+ /* GIC */
>>>+ {
>>>+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
>>>+ QList *redist_region_count;
>>>+ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu",
>>>+ NULL);
>>>+
>>>+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
>>>+ qdev_prop_set_uint32(gicdev, "num-irq",
>>>+ FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
>>>+ redist_region_count = qlist_new();
>>>+ qlist_append_int(redist_region_count, ms->smp.cpus);
>>>+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
>>>+ object_property_set_link(OBJECT(&s->gic), "sysmem",
>>>+ OBJECT(get_system_memory()), &error_fatal);
>>>+ if (!sysbus_realize(gicsbd, errp)) {
>>>+ return;
>>>+ }
>>>+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
>>>+ sysbus_mmio_map(gicsbd, 1,
>>>+ fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
>>>+
>>>+ /*
>>>+ * Wire the outputs from each CPU's generic timer and the GICv3
>>>+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
>>>+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
>>>+ */
>>>+ for (i = 0; i < ms->smp.cpus; i++) {
>>>+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
>>>+ int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
>>>+ qemu_irq irq;
>>>+
>>>+ /*
>>>+ * Mapping from the output timer irq lines from the CPU to the
>>>+ * GIC PPI inputs.
>>>+ */
>>>+ static const int timer_irqs[] = {
>>>+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
>>>+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
>>>+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
>>>+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
>>>+ };
>>>+
>>>+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
>>>+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
>>>+ qdev_connect_gpio_out(cpudev, j, irq);
>>>+ }
>>>+
>>>+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
>>>+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
>>>+ 0, irq);
>>>+
>>>+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
>>>+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
>>>+ irq);
>>>+
>>>+ sysbus_connect_irq(gicsbd, i,
>>>+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
>>>+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
>>>+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
>>>+ sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
>>>+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
>>>+ sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
>>>+ qdev_get_gpio_in(cpudev,
>>>+ ARM_CPU_VFIQ));
>>>+
>>>+ if (kvm_enabled()) {
>>>+ if (pmu) {
>>>+ assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
>>>+ if (kvm_irqchip_in_kernel()) {
>>>+ kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
>>>+ }
>>>+ kvm_arm_pmu_init(&s->cpu[i]);
>>>+ }
>>>+ }
>>>+ }
>>>+ }
>>>+
>>>+ /* UARTs */
>>>+ for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
>>>+ struct {
>>>+ hwaddr addr;
>>>+ unsigned int irq;
>>>+ } serial_table[FSL_IMX8MM_NUM_UARTS] = {
>>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
>>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
>>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
>>>+ { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
>>>+ };
>>>+
>>>+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
>>>+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
>>>+ return;
>>>+ }
>>>+
>>>+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
>>>+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
>>>+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
>>>+ }
>>>+
>>>+ /* Unimplemented devices */
>>>+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
>>>+ switch (i) {
>>>+ case FSL_IMX8MM_GIC_DIST:
>>>+ case FSL_IMX8MM_GIC_REDIST:
>>>+ case FSL_IMX8MM_RAM:
>>>+ case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
>>>+ /* device implemented and treated above */
>>>+ break;
>>>+
>>>+ default:
>>>+ create_unimplemented_device(fsl_imx8mm_memmap[i].name,
>>>+ fsl_imx8mm_memmap[i].addr,
>>>+ fsl_imx8mm_memmap[i].size);
>>>+ break;
>>>+ }
>>>+ }
>>>+}
>>>+
>>>+static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data) {
>>>+ DeviceClass *dc = DEVICE_CLASS(oc);
>>>+
>>>+ dc->realize = fsl_imx8mm_realize;
>>>+
>>>+ dc->desc = "i.MX 8MM SoC";
>>>+}
>>>+
>>>+static const TypeInfo fsl_imx8mm_types[] = {
>>>+ {
>>>+ .name = TYPE_FSL_IMX8MM,
>>>+ .parent = TYPE_SYS_BUS_DEVICE,
>>>+ .instance_size = sizeof(FslImx8mmState),
>>>+ .instance_init = fsl_imx8mm_init,
>>>+ .class_init = fsl_imx8mm_class_init,
>>>+ },
>>>+};
>>>+
>>>+DEFINE_TYPES(fsl_imx8mm_types)
>>>diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c new file mode
>>>100644 index 0000000000..cfb42fe464
>>>--- /dev/null
>>>+++ b/hw/arm/imx8mm-evk.c
>>>@@ -0,0 +1,107 @@
>>>+/*
>>>+ * NXP i.MX 8MM Evaluation Kit System Emulation
>>>+ *
>>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>>+ *
>>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>>+
>>>+#include "qemu/osdep.h"
>>>+#include "system/address-spaces.h"
>>>+#include "hw/arm/boot.h"
>>>+#include "hw/arm/fsl-imx8mm.h"
>>>+#include "hw/arm/machines-qom.h"
>>>+#include "hw/boards.h"
>>>+#include "hw/qdev-properties.h"
>>>+#include "system/kvm.h"
>>>+#include "system/qtest.h"
>>>+#include "qemu/error-report.h"
>>>+#include "qapi/error.h"
>>>+#include <libfdt.h>
>>>+
>>>+static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info,
>>>+void *fdt) {
>>>+ int i, offset;
>>>+
>>>+ /* Temporarily disable following nodes until they are implemented */
>>>+ const char *nodes_to_remove[] = {
>>>+ "nxp,imx8mm-fspi",
>>>+ };
>>>+
>>>+ for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
>>>+ const char *dev_str = nodes_to_remove[i];
>>>+
>>>+ offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
>>>+ while (offset >= 0) {
>>>+ fdt_nop_node(fdt, offset);
>>>+ offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
>>>+ }
>>>+ }
>>>+
>>>+ /* Remove cpu-idle-states property from CPU nodes */
>>>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
>>>+ while (offset >= 0) {
>>>+ fdt_nop_property(fdt, offset, "cpu-idle-states");
>>>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
>>>+ }
>>
>>Removing the idle-states ptoperties is only needed since the CPU goes into deep sleep mode during boot and is unable to wake up, even with an imx_sysctr implementation <https://github.com/shentok/qemu/blob/imx8mp/hw/timer/imx_sysctr.c>. Any idea how this works on real hardware? I've already analyzed the interaction with src and gpc but all interrupt channels seem blocked. Any hint would be very helpful.
>>
>>Thanks,
>>Bernhard
>>
>>>+
>>>+ if (kvm_enabled()) {
>>>+ /* Use system counter frequency from host CPU to fix time in guest */
>>>+ offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
>>>+ while (offset >= 0) {
>>>+ fdt_nop_property(fdt, offset, "clock-frequency");
>>>+ offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
>>>+ }
>>>+ }
>>>+}
>>>+
>>>+static void imx8mm_evk_init(MachineState *machine) {
>>>+ static struct arm_boot_info boot_info;
>>>+ FslImx8mmState *s;
>>>+
>>>+ if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
>>>+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
>>>+ machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
>>>+ exit(1);
>>>+ }
>>>+
>>>+ boot_info = (struct arm_boot_info) {
>>>+ .loader_start = FSL_IMX8MM_RAM_START,
>>>+ .board_id = -1,
>>>+ .ram_size = machine->ram_size,
>>>+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
>>>+ .modify_dtb = imx8mm_evk_modify_dtb,
>>>+ };
>>>+
>>>+ s = FSL_IMX8MM(object_new(TYPE_FSL_IMX8MM));
>>>+ 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_IMX8MM_RAM_START,
>>>+ machine->ram);
>>>+
>>>+ if (!qtest_enabled()) {
>>>+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
>>>+ }
>>>+}
>>>+
>>>+static const char *imx8mm_evk_get_default_cpu_type(const MachineState
>>>+*ms) {
>>>+ if (kvm_enabled()) {
>>>+ return ARM_CPU_TYPE_NAME("host");
>>>+ }
>>>+
>>>+ return ARM_CPU_TYPE_NAME("cortex-a53"); }
>>>+
>>>+static void imx8mm_evk_machine_init(MachineClass *mc) {
>>>+ mc->desc = "NXP i.MX 8MM EVK Board";
>>>+ mc->init = imx8mm_evk_init;
>>>+ mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
>>>+ mc->default_ram_id = "imx8mm-evk.ram";
>>>+ mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type; }
>>>+
>>>+DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
>>>diff --git a/hw/arm/meson.build b/hw/arm/meson.build index
>>>aeaf654790..12ecb824cc 100644
>>>--- a/hw/arm/meson.build
>>>+++ b/hw/arm/meson.build
>>>@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true:
>>>files('armsse.c'))
>>> arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true:
>>>files('fsl-imx7.c', 'mcimx7d-sabre.c'))
>>> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true:
>>>files('fsl-imx8mp.c'))
>>> arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true:
>>>files('imx8mp-evk.c'))
>>>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true:
>>>+files('fsl-imx8mm.c'))
>>>+arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true:
>>>+files('imx8mm-evk.c'))
>>> arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true:
>>>files('smmuv3.c'))
>>> arm_common_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true:
>>>files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
>>> arm_common_ss.add(when: 'CONFIG_NRF51_SOC', if_true:
>>>files('nrf51_soc.c')) diff --git a/include/hw/arm/fsl-imx8mm.h
>>>b/include/hw/arm/fsl-imx8mm.h new file mode 100644 index
>>>0000000000..aa954ea00b
>>>--- /dev/null
>>>+++ b/include/hw/arm/fsl-imx8mm.h
>>>@@ -0,0 +1,156 @@
>>>+/*
>>>+ * i.MX 8MM SoC Definitions
>>>+ *
>>>+ * Copyright (c) 2025, Gaurav Sharma <gaurav.sharma_7@nxp.com>
>>>+ *
>>>+ * SPDX-License-Identifier: GPL-2.0-or-later */
>>>+
>>>+#ifndef FSL_IMX8MM_H
>>>+#define FSL_IMX8MM_H
>>>+
>>>+#include "cpu.h"
>>>+#include "hw/char/imx_serial.h"
>>>+#include "hw/intc/arm_gicv3_common.h"
>>>+#include "qom/object.h"
>>>+#include "qemu/units.h"
>>>+
>>>+#define TYPE_FSL_IMX8MM "fsl-imx8mm"
>>>+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
>>>+
>>>+#define FSL_IMX8MM_RAM_START 0x40000000
>>>+#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
>>>+
>>>+enum FslImx8mmConfiguration {
>>>+ FSL_IMX8MM_NUM_CPUS = 4,
>>>+ FSL_IMX8MM_NUM_IRQS = 128,
>>>+ FSL_IMX8MM_NUM_UARTS = 4,
>>>+};
>>>+
>>>+struct FslImx8mmState {
>>>+ SysBusDevice parent_obj;
>>>+
>>>+ ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
>>>+ GICv3State gic;
>>>+ IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
>>>+};
>>>+
>>>+enum FslImx8mmMemoryRegions {
>>>+ FSL_IMX8MM_A53
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2025-11-18 9:47 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-10 11:22 [PATCH 00/13] Adding comprehensive support for i.MX8MM EVK board Gaurav Sharma
2025-11-10 11:22 ` [PATCH 01/13] hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board Gaurav Sharma
2025-11-11 23:44 ` Bernhard Beschow
2025-11-13 10:52 ` [EXT] " Gaurav Sharma
2025-11-17 13:14 ` Bernhard Beschow
2025-11-18 5:26 ` Gaurav Sharma
2025-11-18 9:46 ` Bernhard Beschow
2025-11-10 11:22 ` [PATCH 02/13] hw/arm/fsl-imx8mm: Implemented CCM(Clock Control Module) and Analog IP Gaurav Sharma
2025-11-10 11:22 ` [PATCH 03/13] hw/arm/fsl-imx8mm: Implemented support for SNVS Gaurav Sharma
2025-11-10 11:22 ` [PATCH 04/13] hw/arm/fsl-imx8mm: Adding support for USDHC storage controllers Gaurav Sharma
2025-11-10 15:05 ` Philippe Mathieu-Daudé
2025-11-11 6:09 ` [EXT] " Gaurav Sharma
2025-11-10 11:22 ` [PATCH 05/13] hw/arm/fsl-imx8mm: Add PCIe support Gaurav Sharma
2025-11-10 15:00 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 06/13] hw/arm/fsl-imx8mm: Add GPIO controllers Gaurav Sharma
2025-11-10 15:02 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 07/13] hw/arm/fsl-imx8mm: Adding support for I2C emulation Gaurav Sharma
2025-11-10 15:07 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 08/13] hw/arm/fsl-imx8mm: Adding support for SPI controller Gaurav Sharma
2025-11-10 15:08 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 09/13] hw/arm/fsl-imx8mm: Adding support for Watchdog Timers Gaurav Sharma
2025-11-10 15:12 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 10/13] hw/arm/fsl-imx8mm: Adding support for General Purpose Timers Gaurav Sharma
2025-11-10 11:22 ` [PATCH 11/13] hw/arm/fsl-imx8mm: Adding support for ENET ethernet controller Gaurav Sharma
2025-11-10 11:22 ` [PATCH 12/13] hw/arm/fsl-imx8mm: Adding support for USB controller Gaurav Sharma
2025-11-10 15:10 ` Philippe Mathieu-Daudé
2025-11-10 11:22 ` [PATCH 13/13] hw/arm/fsl-imx8mm: Adding functional testing of iMX8MM emulation Gaurav Sharma
2025-11-11 23:21 ` Bernhard Beschow
2025-11-12 6:58 ` [EXT] " Gaurav Sharma
2025-11-12 7:05 ` Gaurav Sharma
2025-11-12 11:02 ` Gaurav Sharma
2025-11-12 21:46 ` Bernhard Beschow
2025-11-13 3:03 ` Gaurav Sharma
2025-11-10 14:38 ` [PATCH v2 00/13] Adding comprehensive support for i.MX8MM EVK board Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).