mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 12:23:53 -06:00
hw/arm: Add i.MX 8M Plus EVK board
As a first step, implement the bare minimum: CPUs, RAM, interrupt controller, serial. All other devices of the A53 memory map are represented as TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows for running Linux without it crashing due to invalid memory accesses. Signed-off-by: Bernhard Beschow <shentey@gmail.com> Message-id: 20250223114708.1780-5-shentey@gmail.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> [PMM: drop 'static const' from serial_table[] definition to avoid compile failure on GCC 7.5] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
0f520f0a9d
commit
a4eefc69b2
8 changed files with 689 additions and 0 deletions
|
@ -820,6 +820,15 @@ F: hw/pci-host/designware.c
|
|||
F: include/hw/pci-host/designware.h
|
||||
F: docs/system/arm/mcimx7d-sabre.rst
|
||||
|
||||
MCIMX8MP-EVK / i.MX8MP
|
||||
M: Bernhard Beschow <shentey@gmail.com>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/imx8mp-evk.c
|
||||
F: hw/arm/fsl-imx8mp.c
|
||||
F: include/hw/arm/fsl-imx8mp.h
|
||||
F: docs/system/arm/imx8mp-evk.rst
|
||||
|
||||
MPS2 / MPS3
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
|
|
54
docs/system/arm/imx8mp-evk.rst
Normal file
54
docs/system/arm/imx8mp-evk.rst
Normal file
|
@ -0,0 +1,54 @@
|
|||
NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
|
||||
================================================
|
||||
|
||||
The ``imx8mp-evk`` machine models the i.MX 8M Plus Evaluation Kit, based on an
|
||||
i.MX 8M Plus SoC.
|
||||
|
||||
Supported devices
|
||||
-----------------
|
||||
|
||||
The ``imx8mp-evk`` machine implements the following devices:
|
||||
|
||||
* Up to 4 Cortex-A53 cores
|
||||
* Generic Interrupt Controller (GICv3)
|
||||
* 4 UARTs
|
||||
|
||||
Boot options
|
||||
------------
|
||||
|
||||
The ``imx8mp-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
|
||||
|
||||
$ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
|
||||
$ make freescale_imx8mpevk_defconfig
|
||||
$ make
|
||||
|
||||
Once finished successfully there is an ``output/image`` subfolder. Navigate into
|
||||
it and patch the device tree with the following commands which will remove the
|
||||
``cpu-idle-states`` properties from CPU nodes:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ dtc imx8mp-evk.dtb | sed '/cpu-idle-states/d' > imx8mp-evk-patched.dts
|
||||
$ dtc imx8mp-evk-patched.dts -o imx8mp-evk-patched.dtb
|
||||
|
||||
Now that everything is prepared the machine can be started as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-aarch64 -M imx8mp-evk -smp 4 -m 3G \
|
||||
-display none -serial null -serial stdio \
|
||||
-kernel Image \
|
||||
-dtb imx8mp-evk-patched.dtb \
|
||||
-initrd rootfs.cpio \
|
||||
-append "root=/dev/ram"
|
|
@ -95,6 +95,7 @@ Board-specific documentation
|
|||
arm/imx25-pdk
|
||||
arm/mcimx6ul-evk
|
||||
arm/mcimx7d-sabre
|
||||
arm/imx8mp-evk
|
||||
arm/orangepi
|
||||
arm/raspi
|
||||
arm/collie
|
||||
|
|
|
@ -593,6 +593,18 @@ config FSL_IMX7
|
|||
select UNIMP
|
||||
select USB_CHIPIDEA
|
||||
|
||||
config FSL_IMX8MP
|
||||
bool
|
||||
select ARM_GIC
|
||||
select IMX
|
||||
select UNIMP
|
||||
|
||||
config FSL_IMX8MP_EVK
|
||||
bool
|
||||
default y
|
||||
depends on TCG && AARCH64
|
||||
select FSL_IMX8MP
|
||||
|
||||
config ARM_SMMUV3
|
||||
bool
|
||||
|
||||
|
|
367
hw/arm/fsl-imx8mp.c
Normal file
367
hw/arm/fsl-imx8mp.c
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* i.MX 8M Plus SoC Implementation
|
||||
*
|
||||
* Based on hw/arm/fsl-imx6.c
|
||||
*
|
||||
* Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/arm/bsa.h"
|
||||
#include "hw/arm/fsl-imx8mp.h"
|
||||
#include "hw/intc/arm_gicv3.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/boards.h"
|
||||
#include "system/system.h"
|
||||
#include "target/arm/cpu-qom.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qobject/qlist.h"
|
||||
|
||||
static const struct {
|
||||
hwaddr addr;
|
||||
size_t size;
|
||||
const char *name;
|
||||
} fsl_imx8mp_memmap[] = {
|
||||
[FSL_IMX8MP_RAM] = { FSL_IMX8MP_RAM_START, FSL_IMX8MP_RAM_SIZE_MAX, "ram" },
|
||||
[FSL_IMX8MP_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
|
||||
[FSL_IMX8MP_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
|
||||
[FSL_IMX8MP_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
|
||||
[FSL_IMX8MP_DDR_BLK_CTRL] = { 0x3d000000, 1 * MiB, "ddr_blk_ctrl" },
|
||||
[FSL_IMX8MP_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
|
||||
[FSL_IMX8MP_AUDIO_DSP] = { 0x3b000000, 16 * MiB, "audio_dsp" },
|
||||
[FSL_IMX8MP_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
|
||||
[FSL_IMX8MP_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
|
||||
[FSL_IMX8MP_NPU] = { 0x38500000, 2 * MiB, "npu" },
|
||||
[FSL_IMX8MP_VPU] = { 0x38340000, 2 * MiB, "vpu" },
|
||||
[FSL_IMX8MP_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
|
||||
[FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
|
||||
[FSL_IMX8MP_VPU_G2_DECODER] = { 0x38310000, 2 * MiB, "vpu_g2_decoder" },
|
||||
[FSL_IMX8MP_VPU_G1_DECODER] = { 0x38300000, 2 * MiB, "vpu_g1_decoder" },
|
||||
[FSL_IMX8MP_USB2] = { 0x38200000, 1 * MiB, "usb2" },
|
||||
[FSL_IMX8MP_USB1] = { 0x38100000, 1 * MiB, "usb1" },
|
||||
[FSL_IMX8MP_GPU2D] = { 0x38008000, 32 * KiB, "gpu2d" },
|
||||
[FSL_IMX8MP_GPU3D] = { 0x38000000, 32 * KiB, "gpu3d" },
|
||||
[FSL_IMX8MP_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
|
||||
[FSL_IMX8MP_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
|
||||
[FSL_IMX8MP_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
|
||||
[FSL_IMX8MP_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
|
||||
|
||||
/* AIPS-5 Begin */
|
||||
[FSL_IMX8MP_MU_3_B] = { 0x30e90000, 64 * KiB, "mu_3_b" },
|
||||
[FSL_IMX8MP_MU_3_A] = { 0x30e80000, 64 * KiB, "mu_3_a" },
|
||||
[FSL_IMX8MP_MU_2_B] = { 0x30e70000, 64 * KiB, "mu_2_b" },
|
||||
[FSL_IMX8MP_MU_2_A] = { 0x30e60000, 64 * KiB, "mu_2_a" },
|
||||
[FSL_IMX8MP_EDMA_CHANNELS] = { 0x30e40000, 128 * KiB, "edma_channels" },
|
||||
[FSL_IMX8MP_EDMA_MANAGEMENT_PAGE] = { 0x30e30000, 64 * KiB, "edma_management_page" },
|
||||
[FSL_IMX8MP_AUDIO_BLK_CTRL] = { 0x30e20000, 64 * KiB, "audio_blk_ctrl" },
|
||||
[FSL_IMX8MP_SDMA2] = { 0x30e10000, 64 * KiB, "sdma2" },
|
||||
[FSL_IMX8MP_SDMA3] = { 0x30e00000, 64 * KiB, "sdma3" },
|
||||
[FSL_IMX8MP_AIPS5_CONFIGURATION] = { 0x30df0000, 64 * KiB, "aips5_configuration" },
|
||||
[FSL_IMX8MP_SPBA2] = { 0x30cf0000, 64 * KiB, "spba2" },
|
||||
[FSL_IMX8MP_AUDIO_XCVR_RX] = { 0x30cc0000, 64 * KiB, "audio_xcvr_rx" },
|
||||
[FSL_IMX8MP_HDMI_TX_AUDLNK_MSTR] = { 0x30cb0000, 64 * KiB, "hdmi_tx_audlnk_mstr" },
|
||||
[FSL_IMX8MP_PDM] = { 0x30ca0000, 64 * KiB, "pdm" },
|
||||
[FSL_IMX8MP_ASRC] = { 0x30c90000, 64 * KiB, "asrc" },
|
||||
[FSL_IMX8MP_SAI7] = { 0x30c80000, 64 * KiB, "sai7" },
|
||||
[FSL_IMX8MP_SAI6] = { 0x30c60000, 64 * KiB, "sai6" },
|
||||
[FSL_IMX8MP_SAI5] = { 0x30c50000, 64 * KiB, "sai5" },
|
||||
[FSL_IMX8MP_SAI3] = { 0x30c30000, 64 * KiB, "sai3" },
|
||||
[FSL_IMX8MP_SAI2] = { 0x30c20000, 64 * KiB, "sai2" },
|
||||
[FSL_IMX8MP_SAI1] = { 0x30c10000, 64 * KiB, "sai1" },
|
||||
/* AIPS-5 End */
|
||||
|
||||
/* AIPS-4 Begin */
|
||||
[FSL_IMX8MP_HDMI_TX] = { 0x32fc0000, 128 * KiB, "hdmi_tx" },
|
||||
[FSL_IMX8MP_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
|
||||
[FSL_IMX8MP_HSIO_BLK_CTL] = { 0x32f10000, 64 * KiB, "hsio_blk_ctl" },
|
||||
[FSL_IMX8MP_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
|
||||
[FSL_IMX8MP_MEDIA_BLK_CTL] = { 0x32ec0000, 64 * KiB, "media_blk_ctl" },
|
||||
[FSL_IMX8MP_LCDIF2] = { 0x32e90000, 64 * KiB, "lcdif2" },
|
||||
[FSL_IMX8MP_LCDIF1] = { 0x32e80000, 64 * KiB, "lcdif1" },
|
||||
[FSL_IMX8MP_MIPI_DSI1] = { 0x32e60000, 64 * KiB, "mipi_dsi1" },
|
||||
[FSL_IMX8MP_MIPI_CSI2] = { 0x32e50000, 64 * KiB, "mipi_csi2" },
|
||||
[FSL_IMX8MP_MIPI_CSI1] = { 0x32e40000, 64 * KiB, "mipi_csi1" },
|
||||
[FSL_IMX8MP_IPS_DEWARP] = { 0x32e30000, 64 * KiB, "ips_dewarp" },
|
||||
[FSL_IMX8MP_ISP2] = { 0x32e20000, 64 * KiB, "isp2" },
|
||||
[FSL_IMX8MP_ISP1] = { 0x32e10000, 64 * KiB, "isp1" },
|
||||
[FSL_IMX8MP_ISI] = { 0x32e00000, 64 * KiB, "isi" },
|
||||
[FSL_IMX8MP_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
|
||||
/* AIPS-4 End */
|
||||
|
||||
[FSL_IMX8MP_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
|
||||
|
||||
/* AIPS-3 Begin */
|
||||
[FSL_IMX8MP_ENET2_TSN] = { 0x30bf0000, 64 * KiB, "enet2_tsn" },
|
||||
[FSL_IMX8MP_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
|
||||
[FSL_IMX8MP_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
|
||||
[FSL_IMX8MP_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
|
||||
[FSL_IMX8MP_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
|
||||
[FSL_IMX8MP_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
|
||||
[FSL_IMX8MP_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
|
||||
[FSL_IMX8MP_I2C6] = { 0x30ae0000, 64 * KiB, "i2c6" },
|
||||
[FSL_IMX8MP_I2C5] = { 0x30ad0000, 64 * KiB, "i2c5" },
|
||||
[FSL_IMX8MP_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
|
||||
[FSL_IMX8MP_MU_1_B] = { 0x30ab0000, 64 * KiB, "mu_1_b" },
|
||||
[FSL_IMX8MP_MU_1_A] = { 0x30aa0000, 64 * KiB, "mu_1_a" },
|
||||
[FSL_IMX8MP_AUD_IRQ_STEER] = { 0x30a80000, 64 * KiB, "aud_irq_steer" },
|
||||
[FSL_IMX8MP_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
|
||||
[FSL_IMX8MP_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
|
||||
[FSL_IMX8MP_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
|
||||
[FSL_IMX8MP_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
|
||||
[FSL_IMX8MP_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
|
||||
[FSL_IMX8MP_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
|
||||
[FSL_IMX8MP_CAAM] = { 0x30900000, 256 * KiB, "caam" },
|
||||
[FSL_IMX8MP_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
|
||||
[FSL_IMX8MP_FLEXCAN2] = { 0x308d0000, 64 * KiB, "flexcan2" },
|
||||
[FSL_IMX8MP_FLEXCAN1] = { 0x308c0000, 64 * KiB, "flexcan1" },
|
||||
[FSL_IMX8MP_UART2] = { 0x30890000, 64 * KiB, "uart2" },
|
||||
[FSL_IMX8MP_UART3] = { 0x30880000, 64 * KiB, "uart3" },
|
||||
[FSL_IMX8MP_UART1] = { 0x30860000, 64 * KiB, "uart1" },
|
||||
[FSL_IMX8MP_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
|
||||
[FSL_IMX8MP_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
|
||||
[FSL_IMX8MP_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
|
||||
/* AIPS-3 End */
|
||||
|
||||
/* AIPS-2 Begin */
|
||||
[FSL_IMX8MP_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
|
||||
[FSL_IMX8MP_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
|
||||
[FSL_IMX8MP_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
|
||||
[FSL_IMX8MP_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
|
||||
[FSL_IMX8MP_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
|
||||
[FSL_IMX8MP_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
|
||||
[FSL_IMX8MP_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
|
||||
[FSL_IMX8MP_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
|
||||
[FSL_IMX8MP_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
|
||||
[FSL_IMX8MP_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
|
||||
[FSL_IMX8MP_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
|
||||
[FSL_IMX8MP_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
|
||||
[FSL_IMX8MP_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
|
||||
[FSL_IMX8MP_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
|
||||
/* AIPS-2 End */
|
||||
|
||||
/* AIPS-1 Begin */
|
||||
[FSL_IMX8MP_CSU] = { 0x303e0000, 64 * KiB, "csu" },
|
||||
[FSL_IMX8MP_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
|
||||
[FSL_IMX8MP_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
|
||||
[FSL_IMX8MP_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
|
||||
[FSL_IMX8MP_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
|
||||
[FSL_IMX8MP_SRC] = { 0x30390000, 64 * KiB, "src" },
|
||||
[FSL_IMX8MP_CCM] = { 0x30380000, 64 * KiB, "ccm" },
|
||||
[FSL_IMX8MP_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
|
||||
[FSL_IMX8MP_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
|
||||
[FSL_IMX8MP_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
|
||||
[FSL_IMX8MP_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
|
||||
[FSL_IMX8MP_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
|
||||
[FSL_IMX8MP_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
|
||||
[FSL_IMX8MP_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
|
||||
[FSL_IMX8MP_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
|
||||
[FSL_IMX8MP_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
|
||||
[FSL_IMX8MP_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
|
||||
[FSL_IMX8MP_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
|
||||
[FSL_IMX8MP_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
|
||||
[FSL_IMX8MP_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
|
||||
[FSL_IMX8MP_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
|
||||
[FSL_IMX8MP_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
|
||||
[FSL_IMX8MP_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
|
||||
[FSL_IMX8MP_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
|
||||
[FSL_IMX8MP_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
|
||||
[FSL_IMX8MP_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
|
||||
/* AIPS-1 End */
|
||||
|
||||
[FSL_IMX8MP_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
|
||||
[FSL_IMX8MP_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
|
||||
[FSL_IMX8MP_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
|
||||
[FSL_IMX8MP_OCRAM] = { 0x00900000, 576 * KiB, "ocram" },
|
||||
[FSL_IMX8MP_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
|
||||
[FSL_IMX8MP_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
|
||||
[FSL_IMX8MP_OCRAM_S] = { 0x00180000, 36 * KiB, "ocram_s" },
|
||||
[FSL_IMX8MP_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
|
||||
[FSL_IMX8MP_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
|
||||
[FSL_IMX8MP_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
|
||||
};
|
||||
|
||||
static void fsl_imx8mp_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslImx8mpState *s = FSL_IMX8MP(obj);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
|
||||
g_autofree char *name = g_strdup_printf("cpu%d", i);
|
||||
object_initialize_child(obj, name, &s->cpu[i],
|
||||
ARM_CPU_TYPE_NAME("cortex-a53"));
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
|
||||
|
||||
for (i = 0; i < FSL_IMX8MP_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_imx8mp_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslImx8mpState *s = FSL_IMX8MP(dev);
|
||||
DeviceState *gicdev = DEVICE(&s->gic);
|
||||
int i;
|
||||
|
||||
if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
|
||||
error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
|
||||
TYPE_FSL_IMX8MP, FSL_IMX8MP_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_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
|
||||
fsl_imx8mp_memmap[FSL_IMX8MP_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 (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;
|
||||
|
||||
qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
|
||||
qdev_prop_set_uint32(gicdev, "num-irq",
|
||||
FSL_IMX8MP_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_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr);
|
||||
sysbus_mmio_map(gicsbd, 1, fsl_imx8mp_memmap[FSL_IMX8MP_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_IMX8MP_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));
|
||||
}
|
||||
}
|
||||
|
||||
/* UARTs */
|
||||
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
|
||||
struct {
|
||||
hwaddr addr;
|
||||
unsigned int irq;
|
||||
} serial_table[FSL_IMX8MP_NUM_UARTS] = {
|
||||
{ fsl_imx8mp_memmap[FSL_IMX8MP_UART1].addr, FSL_IMX8MP_UART1_IRQ },
|
||||
{ fsl_imx8mp_memmap[FSL_IMX8MP_UART2].addr, FSL_IMX8MP_UART2_IRQ },
|
||||
{ fsl_imx8mp_memmap[FSL_IMX8MP_UART3].addr, FSL_IMX8MP_UART3_IRQ },
|
||||
{ fsl_imx8mp_memmap[FSL_IMX8MP_UART4].addr, FSL_IMX8MP_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_imx8mp_memmap); i++) {
|
||||
switch (i) {
|
||||
case FSL_IMX8MP_GIC_DIST:
|
||||
case FSL_IMX8MP_GIC_REDIST:
|
||||
case FSL_IMX8MP_RAM:
|
||||
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
|
||||
/* device implemented and treated above */
|
||||
break;
|
||||
|
||||
default:
|
||||
create_unimplemented_device(fsl_imx8mp_memmap[i].name,
|
||||
fsl_imx8mp_memmap[i].addr,
|
||||
fsl_imx8mp_memmap[i].size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = fsl_imx8mp_realize;
|
||||
|
||||
dc->desc = "i.MX 8M Plus SoC";
|
||||
}
|
||||
|
||||
static const TypeInfo fsl_imx8mp_types[] = {
|
||||
{
|
||||
.name = TYPE_FSL_IMX8MP,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(FslImx8mpState),
|
||||
.instance_init = fsl_imx8mp_init,
|
||||
.class_init = fsl_imx8mp_class_init,
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_TYPES(fsl_imx8mp_types)
|
55
hw/arm/imx8mp-evk.c
Normal file
55
hw/arm/imx8mp-evk.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* NXP i.MX 8M Plus Evaluation Kit System Emulation
|
||||
*
|
||||
* Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/arm/fsl-imx8mp.h"
|
||||
#include "hw/boards.h"
|
||||
#include "system/qtest.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
static void imx8mp_evk_init(MachineState *machine)
|
||||
{
|
||||
static struct arm_boot_info boot_info;
|
||||
FslImx8mpState *s;
|
||||
|
||||
if (machine->ram_size > FSL_IMX8MP_RAM_SIZE_MAX) {
|
||||
error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
|
||||
machine->ram_size, FSL_IMX8MP_RAM_SIZE_MAX);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
boot_info = (struct arm_boot_info) {
|
||||
.loader_start = FSL_IMX8MP_RAM_START,
|
||||
.board_id = -1,
|
||||
.ram_size = machine->ram_size,
|
||||
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
|
||||
};
|
||||
|
||||
s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
|
||||
qdev_realize(DEVICE(s), NULL, &error_fatal);
|
||||
|
||||
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
|
||||
machine->ram);
|
||||
|
||||
if (!qtest_enabled()) {
|
||||
arm_load_kernel(&s->cpu[0], machine, &boot_info);
|
||||
}
|
||||
}
|
||||
|
||||
static void imx8mp_evk_machine_init(MachineClass *mc)
|
||||
{
|
||||
mc->desc = "NXP i.MX 8M Plus EVK Board";
|
||||
mc->init = imx8mp_evk_init;
|
||||
mc->max_cpus = FSL_IMX8MP_NUM_CPUS;
|
||||
mc->default_ram_id = "imx8mp-evk.ram";
|
||||
}
|
||||
DEFINE_MACHINE("imx8mp-evk", imx8mp_evk_machine_init)
|
|
@ -54,6 +54,8 @@ arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
|
|||
arm_ss.add(when: 'CONFIG_MUSCA', if_true: files('musca.c'))
|
||||
arm_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
|
||||
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
|
||||
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
|
||||
|
|
189
include/hw/arm/fsl-imx8mp.h
Normal file
189
include/hw/arm/fsl-imx8mp.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* i.MX 8M Plus SoC Definitions
|
||||
*
|
||||
* Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef FSL_IMX8MP_H
|
||||
#define FSL_IMX8MP_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_IMX8MP "fsl-imx8mp"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
|
||||
|
||||
#define FSL_IMX8MP_RAM_START 0x40000000
|
||||
#define FSL_IMX8MP_RAM_SIZE_MAX (8 * GiB)
|
||||
|
||||
enum FslImx8mpConfiguration {
|
||||
FSL_IMX8MP_NUM_CPUS = 4,
|
||||
FSL_IMX8MP_NUM_IRQS = 160,
|
||||
FSL_IMX8MP_NUM_UARTS = 4,
|
||||
};
|
||||
|
||||
struct FslImx8mpState {
|
||||
DeviceState parent_obj;
|
||||
|
||||
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
|
||||
GICv3State gic;
|
||||
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
|
||||
};
|
||||
|
||||
enum FslImx8mpMemoryRegions {
|
||||
FSL_IMX8MP_A53_DAP,
|
||||
FSL_IMX8MP_AIPS1_CONFIGURATION,
|
||||
FSL_IMX8MP_AIPS2_CONFIGURATION,
|
||||
FSL_IMX8MP_AIPS3_CONFIGURATION,
|
||||
FSL_IMX8MP_AIPS4_CONFIGURATION,
|
||||
FSL_IMX8MP_AIPS5_CONFIGURATION,
|
||||
FSL_IMX8MP_ANA_OSC,
|
||||
FSL_IMX8MP_ANA_PLL,
|
||||
FSL_IMX8MP_ANA_TSENSOR,
|
||||
FSL_IMX8MP_APBH_DMA,
|
||||
FSL_IMX8MP_ASRC,
|
||||
FSL_IMX8MP_AUDIO_BLK_CTRL,
|
||||
FSL_IMX8MP_AUDIO_DSP,
|
||||
FSL_IMX8MP_AUDIO_XCVR_RX,
|
||||
FSL_IMX8MP_AUD_IRQ_STEER,
|
||||
FSL_IMX8MP_BOOT_ROM,
|
||||
FSL_IMX8MP_BOOT_ROM_PROTECTED,
|
||||
FSL_IMX8MP_CAAM,
|
||||
FSL_IMX8MP_CAAM_MEM,
|
||||
FSL_IMX8MP_CCM,
|
||||
FSL_IMX8MP_CSU,
|
||||
FSL_IMX8MP_DDR_BLK_CTRL,
|
||||
FSL_IMX8MP_DDR_CTL,
|
||||
FSL_IMX8MP_DDR_PERF_MON,
|
||||
FSL_IMX8MP_DDR_PHY,
|
||||
FSL_IMX8MP_DDR_PHY_BROADCAST,
|
||||
FSL_IMX8MP_ECSPI1,
|
||||
FSL_IMX8MP_ECSPI2,
|
||||
FSL_IMX8MP_ECSPI3,
|
||||
FSL_IMX8MP_EDMA_CHANNELS,
|
||||
FSL_IMX8MP_EDMA_MANAGEMENT_PAGE,
|
||||
FSL_IMX8MP_ENET1,
|
||||
FSL_IMX8MP_ENET2_TSN,
|
||||
FSL_IMX8MP_FLEXCAN1,
|
||||
FSL_IMX8MP_FLEXCAN2,
|
||||
FSL_IMX8MP_GIC_DIST,
|
||||
FSL_IMX8MP_GIC_REDIST,
|
||||
FSL_IMX8MP_GPC,
|
||||
FSL_IMX8MP_GPIO1,
|
||||
FSL_IMX8MP_GPIO2,
|
||||
FSL_IMX8MP_GPIO3,
|
||||
FSL_IMX8MP_GPIO4,
|
||||
FSL_IMX8MP_GPIO5,
|
||||
FSL_IMX8MP_GPT1,
|
||||
FSL_IMX8MP_GPT2,
|
||||
FSL_IMX8MP_GPT3,
|
||||
FSL_IMX8MP_GPT4,
|
||||
FSL_IMX8MP_GPT5,
|
||||
FSL_IMX8MP_GPT6,
|
||||
FSL_IMX8MP_GPU2D,
|
||||
FSL_IMX8MP_GPU3D,
|
||||
FSL_IMX8MP_HDMI_TX,
|
||||
FSL_IMX8MP_HDMI_TX_AUDLNK_MSTR,
|
||||
FSL_IMX8MP_HSIO_BLK_CTL,
|
||||
FSL_IMX8MP_I2C1,
|
||||
FSL_IMX8MP_I2C2,
|
||||
FSL_IMX8MP_I2C3,
|
||||
FSL_IMX8MP_I2C4,
|
||||
FSL_IMX8MP_I2C5,
|
||||
FSL_IMX8MP_I2C6,
|
||||
FSL_IMX8MP_INTERCONNECT,
|
||||
FSL_IMX8MP_IOMUXC,
|
||||
FSL_IMX8MP_IOMUXC_GPR,
|
||||
FSL_IMX8MP_IPS_DEWARP,
|
||||
FSL_IMX8MP_ISI,
|
||||
FSL_IMX8MP_ISP1,
|
||||
FSL_IMX8MP_ISP2,
|
||||
FSL_IMX8MP_LCDIF1,
|
||||
FSL_IMX8MP_LCDIF2,
|
||||
FSL_IMX8MP_MEDIA_BLK_CTL,
|
||||
FSL_IMX8MP_MIPI_CSI1,
|
||||
FSL_IMX8MP_MIPI_CSI2,
|
||||
FSL_IMX8MP_MIPI_DSI1,
|
||||
FSL_IMX8MP_MU_1_A,
|
||||
FSL_IMX8MP_MU_1_B,
|
||||
FSL_IMX8MP_MU_2_A,
|
||||
FSL_IMX8MP_MU_2_B,
|
||||
FSL_IMX8MP_MU_3_A,
|
||||
FSL_IMX8MP_MU_3_B,
|
||||
FSL_IMX8MP_NPU,
|
||||
FSL_IMX8MP_OCOTP_CTRL,
|
||||
FSL_IMX8MP_OCRAM,
|
||||
FSL_IMX8MP_OCRAM_S,
|
||||
FSL_IMX8MP_PCIE1,
|
||||
FSL_IMX8MP_PCIE1_MEM,
|
||||
FSL_IMX8MP_PCIE_PHY1,
|
||||
FSL_IMX8MP_PDM,
|
||||
FSL_IMX8MP_PERFMON1,
|
||||
FSL_IMX8MP_PERFMON2,
|
||||
FSL_IMX8MP_PWM1,
|
||||
FSL_IMX8MP_PWM2,
|
||||
FSL_IMX8MP_PWM3,
|
||||
FSL_IMX8MP_PWM4,
|
||||
FSL_IMX8MP_QOSC,
|
||||
FSL_IMX8MP_QSPI,
|
||||
FSL_IMX8MP_QSPI1_RX_BUFFER,
|
||||
FSL_IMX8MP_QSPI1_TX_BUFFER,
|
||||
FSL_IMX8MP_QSPI_MEM,
|
||||
FSL_IMX8MP_RAM,
|
||||
FSL_IMX8MP_RDC,
|
||||
FSL_IMX8MP_SAI1,
|
||||
FSL_IMX8MP_SAI2,
|
||||
FSL_IMX8MP_SAI3,
|
||||
FSL_IMX8MP_SAI5,
|
||||
FSL_IMX8MP_SAI6,
|
||||
FSL_IMX8MP_SAI7,
|
||||
FSL_IMX8MP_SDMA1,
|
||||
FSL_IMX8MP_SDMA2,
|
||||
FSL_IMX8MP_SDMA3,
|
||||
FSL_IMX8MP_SEMAPHORE1,
|
||||
FSL_IMX8MP_SEMAPHORE2,
|
||||
FSL_IMX8MP_SEMAPHORE_HS,
|
||||
FSL_IMX8MP_SNVS_HP,
|
||||
FSL_IMX8MP_SPBA1,
|
||||
FSL_IMX8MP_SPBA2,
|
||||
FSL_IMX8MP_SRC,
|
||||
FSL_IMX8MP_SYSCNT_CMP,
|
||||
FSL_IMX8MP_SYSCNT_CTRL,
|
||||
FSL_IMX8MP_SYSCNT_RD,
|
||||
FSL_IMX8MP_TCM_DTCM,
|
||||
FSL_IMX8MP_TCM_ITCM,
|
||||
FSL_IMX8MP_TZASC,
|
||||
FSL_IMX8MP_UART1,
|
||||
FSL_IMX8MP_UART2,
|
||||
FSL_IMX8MP_UART3,
|
||||
FSL_IMX8MP_UART4,
|
||||
FSL_IMX8MP_USB1,
|
||||
FSL_IMX8MP_USB2,
|
||||
FSL_IMX8MP_USDHC1,
|
||||
FSL_IMX8MP_USDHC2,
|
||||
FSL_IMX8MP_USDHC3,
|
||||
FSL_IMX8MP_VPU,
|
||||
FSL_IMX8MP_VPU_BLK_CTRL,
|
||||
FSL_IMX8MP_VPU_G1_DECODER,
|
||||
FSL_IMX8MP_VPU_G2_DECODER,
|
||||
FSL_IMX8MP_VPU_VC8000E_ENCODER,
|
||||
FSL_IMX8MP_WDOG1,
|
||||
FSL_IMX8MP_WDOG2,
|
||||
FSL_IMX8MP_WDOG3,
|
||||
};
|
||||
|
||||
enum FslImx8mpIrqs {
|
||||
FSL_IMX8MP_UART1_IRQ = 26,
|
||||
FSL_IMX8MP_UART2_IRQ = 27,
|
||||
FSL_IMX8MP_UART3_IRQ = 28,
|
||||
FSL_IMX8MP_UART4_IRQ = 29,
|
||||
FSL_IMX8MP_UART5_IRQ = 30,
|
||||
FSL_IMX8MP_UART6_IRQ = 16,
|
||||
};
|
||||
|
||||
#endif /* FSL_IMX8MP_H */
|
Loading…
Add table
Add a link
Reference in a new issue