@samitouri / QOSamiQemu / commits / 7bcd1f30bc

hw/arm: Add the i.MX 8MM EVK(Evaluation Kit) board

Implemented CPUs, RAM, UARTs and Interrupt Controller Other peripherals are represented as TYPE_UNIMPLEMENTED_DEVICE Complete memory map of the SoC is provided. Set default RAM size to 2GB and default CPU count to 4 to match the real i.MX8MM EVK hardware configuration. Documentation is shared with imx8mp-evk to avoid duplication. Signed-off-by: Gaurav Sharma <gaurav.sharma_7@nxp.com> [PMM: fixed over-long lines in doc] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Bernhard Beschow <shentey@gmail.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Gaurav Sharma committed Apr 21, 2026 at 12:22 UTC 7bcd1f30bc838eaf841390b6a96e66b7b96e800f
8 files changed +709 -14
MAINTAINERS
+10 -1
@@ -913,6 +913,15 @@ F: hw/pci-host/designware.c
913 F: include/hw/pci-host/designware.h
914 F: docs/system/arm/mcimx7d-sabre.rst
915
916 +MCIMX8MM-EVK / iMX8MM
917 +M: Gaurav Sharma <gaurav.sharma_7@nxp.com>
918 +L: qemu-arm@nongnu.org
919 +S: Maintained
920 +F: hw/arm/fsl-imx8mm.c
921 +F: hw/arm/imx8mm-evk.c
922 +F: include/hw/arm/fsl-imx8mm.h
923 +F: docs/system/arm/imx8m.rst
924 +
925 MCIMX8MP-EVK / i.MX8MP
926 M: Bernhard Beschow <shentey@gmail.com>
927 L: qemu-arm@nongnu.org
@@ -925,7 +934,7 @@ F: hw/rtc/rs5c372.c
934 F: include/hw/arm/fsl-imx8mp.h
935 F: include/hw/misc/imx8mp_*.h
936 F: include/hw/pci-host/fsl_imx8m_phy.h
928 -F: docs/system/arm/imx8mp-evk.rst
937 +F: docs/system/arm/imx8m.rst
938 F: tests/functional/aarch64/test_imx8mp_evk.py
939 F: tests/qtest/rs5c372-test.c
940
docs/system/arm/imx8m.rst renamed
+37 -12
@@ -1,13 +1,15 @@
1 -NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
2 -================================================
1 +NXP i.MX 8M Plus and i.MX 8M Mini Evaluation Kits (``imx8mp-evk``, ``imx8mm-evk``)
2 +==================================================================================
3
4 -The ``imx8mp-evk`` machine models the i.MX 8M Plus Evaluation Kit, based on an
5 -i.MX 8M Plus SoC.
4 +The ``imx8mp-evk`` and ``imx8mm-evk`` machine models the i.MX 8M Plus
5 +and i.MX 8M Mini Evaluation Kits, based on i.MX 8M Plus and i.MX8M
6 +Mini SoCs.
7
8 Supported devices
9 -----------------
10
10 -The ``imx8mp-evk`` machine implements the following devices:
11 +The ``imx8mp-evk`` and ``imx8mm-evk`` machines implement the
12 +following devices:
13
14 * Up to 4 Cortex-A53 cores
15 * Generic Interrupt Controller (GICv3)
@@ -27,8 +29,8 @@ The ``imx8mp-evk`` machine implements the following devices:
29 Boot options
30 ------------
31
30 -The ``imx8mp-evk`` machine can start a Linux kernel directly using the standard
31 -``-kernel`` functionality.
32 +The ``imx8mp-evk`` and ``imx8mm-evk`` machines can start a Linux
33 +kernel directly using the standard ``-kernel`` functionality.
34
35 Direct Linux Kernel Boot
36 ''''''''''''''''''''''''
@@ -38,11 +40,20 @@ is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
40 of writing and involves two steps. First run the following commands in the
41 toplevel directory of the Buildroot source tree:
42
43 +For i.MX 8M Plus EVK:
44 +
45 .. code-block:: bash
46
47 $ make freescale_imx8mpevk_defconfig
48 $ make
49
50 +For i.MX 8M Mini EVK:
51 +
52 +.. code-block:: bash
53 +
54 + $ make freescale_imx8mmevk_defconfig
55 + $ make
56 +
57 Once finished successfully there is an ``output/image`` subfolder. Navigate into
58 it and resize the SD card image to a power of two:
59
@@ -52,6 +63,8 @@ it and resize the SD card image to a power of two:
63
64 Now that everything is prepared the machine can be started as follows:
65
66 +For i.MX 8M Plus EVK:
67 +
68 .. code-block:: bash
69
70 $ qemu-system-aarch64 -M imx8mp-evk \
@@ -61,6 +74,16 @@ Now that everything is prepared the machine can be started as follows:
74 -append "root=/dev/mmcblk2p2" \
75 -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
76
77 +For i.MX 8M Mini EVK:
78 +
79 +.. code-block:: bash
80 +
81 + $ qemu-system-aarch64 -M imx8mm-evk -smp 4 -m 2G \
82 + -display none -serial null -serial stdio \
83 + -kernel Image \
84 + -dtb imx8mm-evk.dtb \
85 + -append "root=/dev/mmcblk2p2" \
86 + -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
87
88 KVM Acceleration
89 ----------------
@@ -69,11 +92,13 @@ To enable hardware-assisted acceleration via KVM, append
92 ``-accel kvm`` to the command line. While this speeds up performance
93 significantly, be aware of the following limitations:
94
72 -* The ``imx8mp-evk`` machine is not included under the "virtualization use case"
73 - of :doc:`QEMU's security policy </system/security>`. This means that you
74 - should not trust that it can contain malicious guests, whether it is run
75 - using TCG or KVM. If you don't trust your guests and you're relying on QEMU to
76 - be the security boundary, you want to choose another machine such as ``virt``.
95 +* The ``imx8mp-evk`` and ``imx8mm-evk`` machines are not included
96 + under the "virtualization use case" of :doc:`QEMU's security
97 + policy </system/security>`. This means that you should not trust that
98 + it can contain malicious guests, whether it is run using TCG or KVM.
99 + If you don't trust your guests and you're relying on QEMU to be the
100 + security boundary, you want to choose another machine such as
101 + ``virt``.
102 * Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
103 This is a limitation of KVM and may not work with guests with a tight
104 dependency on Cortex-A53.
docs/system/target-arm.rst
+1 -1
@@ -95,7 +95,7 @@ Board-specific documentation
95 arm/imx25-pdk
96 arm/mcimx6ul-evk
97 arm/mcimx7d-sabre
98 - arm/imx8mp-evk
98 + arm/imx8m
99 arm/orangepi
100 arm/raspi
101 arm/collie
hw/arm/Kconfig
+12
@@ -617,6 +617,18 @@ config FSL_IMX8MP_EVK
617 depends on TCG
618 select FSL_IMX8MP
619
620 +config FSL_IMX8MM
621 + bool
622 + select ARM_GIC
623 + select IMX
624 +
625 +config FSL_IMX8MM_EVK
626 + bool
627 + default y
628 + depends on AARCH64
629 + depends on TCG
630 + select FSL_IMX8MM
631 +
632 config ARM_SMMUV3_ACCEL
633 bool
634 depends on ARM_SMMUV3
hw/arm/fsl-imx8mm.c new
+377
@@ -0,0 +1,377 @@
1 +/*
2 + * i.MX 8MM SoC Implementation
3 + *
4 + * Based on hw/arm/fsl-imx6.c
5 + *
6 + * Copyright (c) 2025, NXP Semiconductors
7 + * Author: Gaurav Sharma <gaurav.sharma_7@nxp.com>
8 + *
9 + * SPDX-License-Identifier: GPL-2.0-or-later
10 + *
11 + * iMX8MM Reference Manual - https://www.nxp.com/products/i.MX8MMINI -> Documentation
12 + */
13 +
14 +#include "qemu/osdep.h"
15 +#include "system/address-spaces.h"
16 +#include "hw/arm/bsa.h"
17 +#include "hw/arm/fsl-imx8mm.h"
18 +#include "hw/misc/unimp.h"
19 +#include "hw/core/boards.h"
20 +#include "system/kvm.h"
21 +#include "system/system.h"
22 +#include "target/arm/cpu.h"
23 +#include "target/arm/cpu-qom.h"
24 +#include "target/arm/kvm_arm.h"
25 +#include "qapi/error.h"
26 +#include "qobject/qlist.h"
27 +
28 +static const struct {
29 + hwaddr addr;
30 + size_t size;
31 + const char *name;
32 +} fsl_imx8mm_memmap[] = {
33 + [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
34 + [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
35 + [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
36 + [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
37 + [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
38 + [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
39 + [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
40 + [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
41 + [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
42 + [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
43 + [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
44 + [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
45 + [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
46 + [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
47 + [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
48 + [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
49 + [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
50 + [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
51 + [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
52 + [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
53 +
54 + /* AIPS-4 Begin */
55 + [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
56 + [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
57 + [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
58 + [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
59 + [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
60 + [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
61 + [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
62 + /* AIPS-4 End */
63 +
64 + [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
65 +
66 + /* AIPS-3 Begin */
67 + [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
68 + [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
69 + [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
70 + [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
71 + [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
72 + [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
73 + [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
74 + [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
75 + [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
76 + [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
77 + [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
78 + [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
79 + [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
80 + [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
81 + [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
82 + [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
83 + [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
84 + [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
85 + [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
86 + [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
87 + [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
88 + [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
89 + [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
90 + /* AIPS-3 End */
91 +
92 + /* AIPS-2 Begin */
93 + [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
94 + [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
95 + [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
96 + [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
97 + [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
98 + [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
99 + [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
100 + [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
101 + [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
102 + [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
103 + [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
104 + [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
105 + [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
106 + [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
107 + /* AIPS-2 End */
108 +
109 + /* AIPS-1 Begin */
110 + [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
111 + [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
112 + [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
113 + [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
114 + [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
115 + [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
116 + [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
117 + [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
118 + [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
119 + [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
120 + [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
121 + [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
122 + [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
123 + [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
124 + [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
125 + [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
126 + [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
127 + [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
128 + [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
129 + [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
130 + [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
131 + [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
132 + [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
133 + [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
134 + [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
135 + [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
136 + [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
137 + [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
138 + [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
139 + [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
140 + [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
141 + [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
142 + [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
143 +
144 + /* AIPS-1 End */
145 +
146 + [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
147 + [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
148 + [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
149 + [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
150 + [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
151 + [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
152 + [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
153 + [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
154 + [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
155 + [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
156 +};
157 +
158 +static void fsl_imx8mm_init(Object *obj)
159 +{
160 + MachineState *ms = MACHINE(qdev_get_machine());
161 + FslImx8mmState *s = FSL_IMX8MM(obj);
162 + const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
163 + int i;
164 +
165 + for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MM_NUM_CPUS); i++) {
166 + g_autofree char *name = g_strdup_printf("cpu%d", i);
167 + object_initialize_child(obj, name, &s->cpu[i], cpu_type);
168 + }
169 +
170 + object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
171 +
172 + for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
173 + g_autofree char *name = g_strdup_printf("uart%d", i + 1);
174 + object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
175 + }
176 +
177 +}
178 +
179 +static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
180 +{
181 + MachineState *ms = MACHINE(qdev_get_machine());
182 + FslImx8mmState *s = FSL_IMX8MM(dev);
183 + DeviceState *gicdev = DEVICE(&s->gic);
184 + int i;
185 +
186 + if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
187 + error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
188 + TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
189 + return;
190 + }
191 +
192 + /* CPUs */
193 + for (i = 0; i < ms->smp.cpus; i++) {
194 + /* On uniprocessor, the CBAR is set to 0 */
195 + if (ms->smp.cpus > 1 &&
196 + object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
197 + object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
198 + fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
199 + &error_abort);
200 + }
201 +
202 + /*
203 + * CNTFID0 base frequency in Hz of system counter
204 + */
205 + object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
206 + &error_abort);
207 +
208 + if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
209 + object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
210 + !kvm_enabled(), &error_abort);
211 + }
212 +
213 + if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
214 + object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
215 + !kvm_enabled(), &error_abort);
216 + }
217 +
218 + if (i) {
219 + /*
220 + * Secondary CPUs start in powered-down state (and can be
221 + * powered up via the SRC system reset controller)
222 + */
223 + object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
224 + true, &error_abort);
225 + }
226 +
227 + if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
228 + return;
229 + }
230 + }
231 +
232 + /* GIC */
233 + {
234 + SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
235 + QList *redist_region_count;
236 + bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
237 +
238 + qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
239 + qdev_prop_set_uint32(gicdev, "num-irq",
240 + FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
241 + redist_region_count = qlist_new();
242 + qlist_append_int(redist_region_count, ms->smp.cpus);
243 + qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
244 + object_property_set_link(OBJECT(&s->gic), "sysmem",
245 + OBJECT(get_system_memory()), &error_fatal);
246 + if (!sysbus_realize(gicsbd, errp)) {
247 + return;
248 + }
249 + sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
250 + sysbus_mmio_map(gicsbd, 1, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
251 +
252 + /*
253 + * Wire the outputs from each CPU's generic timer and the GICv3
254 + * maintenance interrupt signal to the appropriate GIC PPI inputs, and
255 + * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
256 + */
257 + for (i = 0; i < ms->smp.cpus; i++) {
258 + DeviceState *cpudev = DEVICE(&s->cpu[i]);
259 + int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
260 + qemu_irq irq;
261 +
262 + /*
263 + * Mapping from the output timer irq lines from the CPU to the
264 + * GIC PPI inputs.
265 + */
266 + static const int timer_irqs[] = {
267 + [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
268 + [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
269 + [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
270 + [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
271 + };
272 +
273 + for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
274 + irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
275 + qdev_connect_gpio_out(cpudev, j, irq);
276 + }
277 +
278 + irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
279 + qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
280 + 0, irq);
281 +
282 + irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
283 + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
284 +
285 + sysbus_connect_irq(gicsbd, i,
286 + qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
287 + sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
288 + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
289 + sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
290 + qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
291 + sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
292 + qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
293 +
294 + if (kvm_enabled()) {
295 + if (pmu) {
296 + assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
297 + if (kvm_irqchip_in_kernel()) {
298 + kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
299 + }
300 + kvm_arm_pmu_init(&s->cpu[i]);
301 + }
302 + }
303 + }
304 + }
305 +
306 + /* UARTs */
307 + for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
308 + static const struct {
309 + hwaddr addr;
310 + unsigned int irq;
311 + } serial_table[FSL_IMX8MM_NUM_UARTS] = {
312 + { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
313 + { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
314 + { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
315 + { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
316 + };
317 +
318 + qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
319 + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
320 + return;
321 + }
322 +
323 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
324 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
325 + qdev_get_gpio_in(gicdev, serial_table[i].irq));
326 + }
327 +
328 + /* On-Chip RAM */
329 + if (!memory_region_init_ram(&s->ocram, OBJECT(dev), "imx8mm.ocram",
330 + fsl_imx8mm_memmap[FSL_IMX8MM_OCRAM].size,
331 + errp)) {
332 + return;
333 + }
334 + memory_region_add_subregion(get_system_memory(),
335 + fsl_imx8mm_memmap[FSL_IMX8MM_OCRAM].addr,
336 + &s->ocram);
337 +
338 + /* Unimplemented devices */
339 + for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
340 + switch (i) {
341 + case FSL_IMX8MM_GIC_DIST:
342 + case FSL_IMX8MM_GIC_REDIST:
343 + case FSL_IMX8MM_RAM:
344 + case FSL_IMX8MM_OCRAM:
345 + case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
346 + /* device implemented and treated above */
347 + break;
348 +
349 + default:
350 + create_unimplemented_device(fsl_imx8mm_memmap[i].name,
351 + fsl_imx8mm_memmap[i].addr,
352 + fsl_imx8mm_memmap[i].size);
353 + break;
354 + }
355 + }
356 +}
357 +
358 +static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data)
359 +{
360 + DeviceClass *dc = DEVICE_CLASS(oc);
361 +
362 + dc->realize = fsl_imx8mm_realize;
363 +
364 + dc->desc = "i.MX 8MM SoC";
365 +}
366 +
367 +static const TypeInfo fsl_imx8mm_types[] = {
368 + {
369 + .name = TYPE_FSL_IMX8MM,
370 + .parent = TYPE_SYS_BUS_DEVICE,
371 + .instance_size = sizeof(FslImx8mmState),
372 + .instance_init = fsl_imx8mm_init,
373 + .class_init = fsl_imx8mm_class_init,
374 + },
375 +};
376 +
377 +DEFINE_TYPES(fsl_imx8mm_types)
hw/arm/imx8mm-evk.c new
+112
@@ -0,0 +1,112 @@
1 +/*
2 + * NXP i.MX 8MM Evaluation Kit System Emulation
3 + *
4 + * Copyright (c) 2025, NXP Semiconductors
5 + * Author: Gaurav Sharma <gaurav.sharma_7@nxp.com>
6 + *
7 + * SPDX-License-Identifier: GPL-2.0-or-later
8 + */
9 +
10 +#include "qemu/osdep.h"
11 +#include "system/address-spaces.h"
12 +#include "hw/arm/boot.h"
13 +#include "hw/arm/fsl-imx8mm.h"
14 +#include "hw/arm/machines-qom.h"
15 +#include "hw/core/boards.h"
16 +#include "hw/core/qdev-properties.h"
17 +#include "system/kvm.h"
18 +#include "system/qtest.h"
19 +#include "qemu/error-report.h"
20 +#include "qapi/error.h"
21 +#include <libfdt.h>
22 +
23 +static void imx8mm_evk_modify_dtb(const struct arm_boot_info *info, void *fdt)
24 +{
25 + int i, offset;
26 +
27 + /* Temporarily disable following nodes until they are implemented */
28 + const char *nodes_to_remove[] = {
29 + "nxp,imx8mm-fspi",
30 + "fsl,imx8mm-mipi-csi",
31 + "fsl,imx8mm-mipi-dsim"
32 + };
33 +
34 + for (i = 0; i < ARRAY_SIZE(nodes_to_remove); i++) {
35 + const char *dev_str = nodes_to_remove[i];
36 +
37 + offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
38 + while (offset >= 0) {
39 + fdt_nop_node(fdt, offset);
40 + offset = fdt_node_offset_by_compatible(fdt, offset, dev_str);
41 + }
42 + }
43 +
44 + /* Remove cpu-idle-states property from CPU nodes */
45 + offset = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a53");
46 + while (offset >= 0) {
47 + fdt_nop_property(fdt, offset, "cpu-idle-states");
48 + offset = fdt_node_offset_by_compatible(fdt, offset, "arm,cortex-a53");
49 + }
50 +
51 + if (kvm_enabled()) {
52 + /* Use system counter frequency from host CPU to fix time in guest */
53 + offset = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
54 + while (offset >= 0) {
55 + fdt_nop_property(fdt, offset, "clock-frequency");
56 + offset = fdt_node_offset_by_compatible(fdt, offset, "arm,armv8-timer");
57 + }
58 + }
59 +}
60 +
61 +static void imx8mm_evk_init(MachineState *machine)
62 +{
63 + static struct arm_boot_info boot_info;
64 + FslImx8mmState *s;
65 +
66 + if (machine->ram_size > FSL_IMX8MM_RAM_SIZE_MAX) {
67 + error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
68 + machine->ram_size, FSL_IMX8MM_RAM_SIZE_MAX);
69 + exit(1);
70 + }
71 +
72 + boot_info = (struct arm_boot_info) {
73 + .loader_start = FSL_IMX8MM_RAM_START,
74 + .board_id = -1,
75 + .ram_size = machine->ram_size,
76 + .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
77 + .modify_dtb = imx8mm_evk_modify_dtb,
78 + };
79 +
80 + s = FSL_IMX8MM(object_new_with_props(TYPE_FSL_IMX8MM, OBJECT(machine),
81 + "soc", &error_fatal, NULL));
82 + sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal);
83 +
84 + memory_region_add_subregion(get_system_memory(), FSL_IMX8MM_RAM_START,
85 + machine->ram);
86 +
87 + if (!qtest_enabled()) {
88 + arm_load_kernel(&s->cpu[0], machine, &boot_info);
89 + }
90 +}
91 +
92 +static const char *imx8mm_evk_get_default_cpu_type(const MachineState *ms)
93 +{
94 + if (kvm_enabled()) {
95 + return ARM_CPU_TYPE_NAME("host");
96 + }
97 +
98 + return ARM_CPU_TYPE_NAME("cortex-a53");
99 +}
100 +
101 +static void imx8mm_evk_machine_init(MachineClass *mc)
102 +{
103 + mc->desc = "NXP i.MX 8MM EVK Board";
104 + mc->init = imx8mm_evk_init;
105 + mc->max_cpus = FSL_IMX8MM_NUM_CPUS;
106 + mc->default_cpus = FSL_IMX8MM_NUM_CPUS;
107 + mc->default_ram_size = 2 * GiB;
108 + mc->default_ram_id = "imx8mm-evk.ram";
109 + mc->get_default_cpu_type = imx8mm_evk_get_default_cpu_type;
110 +}
111 +
112 +DEFINE_MACHINE_AARCH64("imx8mm-evk", imx8mm_evk_machine_init)
hw/arm/meson.build
+2
@@ -84,6 +84,8 @@ arm_common_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
84 arm_common_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
85 arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
86 arm_common_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
87 +arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM', if_true: files('fsl-imx8mm.c'))
88 +arm_common_ss.add(when: 'CONFIG_FSL_IMX8MM_EVK', if_true: files('imx8mm-evk.c'))
89 arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
90 arm_common_ss.add(when: 'CONFIG_ARM_SMMUV3_ACCEL', if_true: files('smmuv3-accel.c'))
91 stub_ss.add(files('smmuv3-accel-stubs.c'))
include/hw/arm/fsl-imx8mm.h new
+158
@@ -0,0 +1,158 @@
1 +/*
2 + * i.MX 8MM SoC Definitions
3 + *
4 + * Copyright (c) 2025, NXP Semiconductors
5 + * Author: Gaurav Sharma <gaurav.sharma_7@nxp.com>
6 + *
7 + * SPDX-License-Identifier: GPL-2.0-or-later
8 + */
9 +
10 +#ifndef FSL_IMX8MM_H
11 +#define FSL_IMX8MM_H
12 +
13 +#include "cpu.h"
14 +#include "hw/char/imx_serial.h"
15 +#include "hw/intc/arm_gicv3_common.h"
16 +#include "qom/object.h"
17 +#include "qemu/units.h"
18 +
19 +#define TYPE_FSL_IMX8MM "fsl-imx8mm"
20 +OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mmState, FSL_IMX8MM)
21 +
22 +#define FSL_IMX8MM_RAM_START 0x40000000
23 +#define FSL_IMX8MM_RAM_SIZE_MAX (4 * GiB)
24 +
25 +enum FslImx8mmConfiguration {
26 + FSL_IMX8MM_NUM_CPUS = 4,
27 + FSL_IMX8MM_NUM_IRQS = 128,
28 + FSL_IMX8MM_NUM_UARTS = 4,
29 +};
30 +
31 +struct FslImx8mmState {
32 + SysBusDevice parent_obj;
33 +
34 + ARMCPU cpu[FSL_IMX8MM_NUM_CPUS];
35 + GICv3State gic;
36 + IMXSerialState uart[FSL_IMX8MM_NUM_UARTS];
37 + MemoryRegion ocram;
38 +};
39 +
40 +enum FslImx8mmMemoryRegions {
41 + FSL_IMX8MM_A53_DAP,
42 + FSL_IMX8MM_AIPS1_CONFIGURATION,
43 + FSL_IMX8MM_AIPS2_CONFIGURATION,
44 + FSL_IMX8MM_AIPS3_CONFIGURATION,
45 + FSL_IMX8MM_AIPS4_CONFIGURATION,
46 + FSL_IMX8MM_ANA_OSC,
47 + FSL_IMX8MM_ANA_PLL,
48 + FSL_IMX8MM_ANA_TSENSOR,
49 + FSL_IMX8MM_APBH_DMA,
50 + FSL_IMX8MM_BOOT_ROM,
51 + FSL_IMX8MM_BOOT_ROM_PROTECTED,
52 + FSL_IMX8MM_CAAM,
53 + FSL_IMX8MM_CAAM_MEM,
54 + FSL_IMX8MM_CCM,
55 + FSL_IMX8MM_CSU,
56 + FSL_IMX8MM_DDR_CTL,
57 + FSL_IMX8MM_DDR_PERF_MON,
58 + FSL_IMX8MM_DDR_PHY,
59 + FSL_IMX8MM_DDR_PHY_BROADCAST,
60 + FSL_IMX8MM_ECSPI1,
61 + FSL_IMX8MM_ECSPI2,
62 + FSL_IMX8MM_ECSPI3,
63 + FSL_IMX8MM_ENET1,
64 + FSL_IMX8MM_GIC_DIST,
65 + FSL_IMX8MM_GIC_REDIST,
66 + FSL_IMX8MM_GPC,
67 + FSL_IMX8MM_GPIO1,
68 + FSL_IMX8MM_GPIO2,
69 + FSL_IMX8MM_GPIO3,
70 + FSL_IMX8MM_GPIO4,
71 + FSL_IMX8MM_GPIO5,
72 + FSL_IMX8MM_GPT1,
73 + FSL_IMX8MM_GPT2,
74 + FSL_IMX8MM_GPT3,
75 + FSL_IMX8MM_GPT4,
76 + FSL_IMX8MM_GPT5,
77 + FSL_IMX8MM_GPT6,
78 + FSL_IMX8MM_GPU2D,
79 + FSL_IMX8MM_I2C1,
80 + FSL_IMX8MM_I2C2,
81 + FSL_IMX8MM_I2C3,
82 + FSL_IMX8MM_I2C4,
83 + FSL_IMX8MM_INTERCONNECT,
84 + FSL_IMX8MM_IOMUXC,
85 + FSL_IMX8MM_IOMUXC_GPR,
86 + FSL_IMX8MM_MEDIA_BLK_CTL,
87 + FSL_IMX8MM_LCDIF,
88 + FSL_IMX8MM_MIPI_CSI,
89 + FSL_IMX8MM_MIPI_DSI,
90 + FSL_IMX8MM_MU_A,
91 + FSL_IMX8MM_MU_B,
92 + FSL_IMX8MM_OCOTP_CTRL,
93 + FSL_IMX8MM_OCRAM,
94 + FSL_IMX8MM_OCRAM_S,
95 + FSL_IMX8MM_PCIE1,
96 + FSL_IMX8MM_PCIE1_MEM,
97 + FSL_IMX8MM_PCIE_PHY1,
98 + FSL_IMX8MM_PERFMON1,
99 + FSL_IMX8MM_PERFMON2,
100 + FSL_IMX8MM_PWM1,
101 + FSL_IMX8MM_PWM2,
102 + FSL_IMX8MM_PWM3,
103 + FSL_IMX8MM_PWM4,
104 + FSL_IMX8MM_QOSC,
105 + FSL_IMX8MM_QSPI,
106 + FSL_IMX8MM_QSPI1_RX_BUFFER,
107 + FSL_IMX8MM_QSPI1_TX_BUFFER,
108 + FSL_IMX8MM_QSPI_MEM,
109 + FSL_IMX8MM_RAM,
110 + FSL_IMX8MM_RDC,
111 + FSL_IMX8MM_SAI1,
112 + FSL_IMX8MM_SAI2,
113 + FSL_IMX8MM_SAI3,
114 + FSL_IMX8MM_SAI5,
115 + FSL_IMX8MM_SAI6,
116 + FSL_IMX8MM_SDMA1,
117 + FSL_IMX8MM_SDMA2,
118 + FSL_IMX8MM_SDMA3,
119 + FSL_IMX8MM_SEMAPHORE1,
120 + FSL_IMX8MM_SEMAPHORE2,
121 + FSL_IMX8MM_SEMAPHORE_HS,
122 + FSL_IMX8MM_SNVS_HP,
123 + FSL_IMX8MM_SPBA1,
124 + FSL_IMX8MM_SRC,
125 + FSL_IMX8MM_SYSCNT_CMP,
126 + FSL_IMX8MM_SYSCNT_CTRL,
127 + FSL_IMX8MM_SYSCNT_RD,
128 + FSL_IMX8MM_TCM_DTCM,
129 + FSL_IMX8MM_TCM_ITCM,
130 + FSL_IMX8MM_TZASC,
131 + FSL_IMX8MM_UART1,
132 + FSL_IMX8MM_UART2,
133 + FSL_IMX8MM_UART3,
134 + FSL_IMX8MM_UART4,
135 + FSL_IMX8MM_USB1,
136 + FSL_IMX8MM_USB2,
137 + FSL_IMX8MM_USB1_OTG,
138 + FSL_IMX8MM_USB2_OTG,
139 + FSL_IMX8MM_USDHC1,
140 + FSL_IMX8MM_USDHC2,
141 + FSL_IMX8MM_USDHC3,
142 + FSL_IMX8MM_VPU,
143 + FSL_IMX8MM_VPU_BLK_CTRL,
144 + FSL_IMX8MM_VPU_G1_DECODER,
145 + FSL_IMX8MM_VPU_G2_DECODER,
146 + FSL_IMX8MM_WDOG1,
147 + FSL_IMX8MM_WDOG2,
148 + FSL_IMX8MM_WDOG3,
149 +};
150 +
151 +enum FslImx8mmIrqs {
152 + FSL_IMX8MM_UART1_IRQ = 26,
153 + FSL_IMX8MM_UART2_IRQ = 27,
154 + FSL_IMX8MM_UART3_IRQ = 28,
155 + FSL_IMX8MM_UART4_IRQ = 29,
156 +};
157 +
158 +#endif /* FSL_IMX8MM_H */