diff --git a/boards/arm/mimx8mp_evk/CMakeLists.txt b/boards/arm/mimx8mp_evk/CMakeLists.txt new file mode 100644 index 00000000000..8b93272d7c3 --- /dev/null +++ b/boards/arm/mimx8mp_evk/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_library() +zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_library_sources(pinmux.c) diff --git a/boards/arm/mimx8mp_evk/Kconfig.board b/boards/arm/mimx8mp_evk/Kconfig.board new file mode 100644 index 00000000000..1595301fa29 --- /dev/null +++ b/boards/arm/mimx8mp_evk/Kconfig.board @@ -0,0 +1,9 @@ +# MIMX8MP EVK board + +# Copyright (c) 2021, Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MIMX8MP_EVK + bool "NXP i.MX8M Plus EVK" + depends on SOC_SERIES_IMX8ML_M7 + select SOC_PART_NUMBER_MIMX8ML8DVNLZ diff --git a/boards/arm/mimx8mp_evk/Kconfig.defconfig b/boards/arm/mimx8mp_evk/Kconfig.defconfig new file mode 100644 index 00000000000..41d7a120fd1 --- /dev/null +++ b/boards/arm/mimx8mp_evk/Kconfig.defconfig @@ -0,0 +1,18 @@ +# MIMX8MP EVK board defconfig + +# Copyright (c) 2021, Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MIMX8MP_EVK + +config BOARD + default "mimx8mp_evk" + +if !XIP +config FLASH_SIZE + default 0 +config FLASH_BASE_ADDRESS + default 0 +endif + +endif # BOARD_MIMX8MP_EVK diff --git a/boards/arm/mimx8mp_evk/board.cmake b/boards/arm/mimx8mp_evk/board.cmake new file mode 100644 index 00000000000..d773ef92919 --- /dev/null +++ b/boards/arm/mimx8mp_evk/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_set_debugger_ifnset(jlink) +board_set_flasher_ifnset(jlink) + +board_runner_args(jlink "--device=MIMX8ML8_M7") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) \ No newline at end of file diff --git a/boards/arm/mimx8mp_evk/doc/img/I.MX8MPLUS-PLUS-EVK-TOP.png b/boards/arm/mimx8mp_evk/doc/img/I.MX8MPLUS-PLUS-EVK-TOP.png new file mode 100644 index 00000000000..74830f362c8 Binary files /dev/null and b/boards/arm/mimx8mp_evk/doc/img/I.MX8MPLUS-PLUS-EVK-TOP.png differ diff --git a/boards/arm/mimx8mp_evk/doc/index.rst b/boards/arm/mimx8mp_evk/doc/index.rst new file mode 100644 index 00000000000..b3456d17d05 --- /dev/null +++ b/boards/arm/mimx8mp_evk/doc/index.rst @@ -0,0 +1,190 @@ +.. _mimx8ml_evk: + +NXP MIMX8MP EVK +############### + +Overview +******** + +i.MX8M Plus EVK board is based on NXP i.MX8M Plus applications +processor, composed of a quad Cortex®-A53 cluster and a single Cortex®-M7 core. +Zephyr OS is ported to run on the Cortex®-M7 core. + +- Board features: + + - RAM: 6GB LPDDR4 + - Storage: + + - SanDisk 32GB eMMC5.1 + - Micron 32MB QSPI NOR + - microSD Socket + - Wireless: + + - WiFi: 2.4/5GHz IEEE 802.11b/g/n/ac + - Bluetooth: v4.2 + - USB: + + - USB 3.0 Type C for Power + - USB 3.0 Type A + - USB 3.0 Type C + - 2x 10/100/1000 Ethernet (1x w/ TSN) + - PCI-E M.2 + - Connectors: + + - 40-Pin Dual Row Header + - LEDs: + + - 1x Power status LED + - 1x UART LED + - Debug + + - JTAG connector + - MicroUSB for UART debug, two COM ports for A53 and one for M7 + +.. image:: img/I.MX8MPLUS-PLUS-EVK-TOP.png + :width: 720px + :align: center + :height: 405px + :alt: MIMX8MP EVK + +More information about the board can be found at the +`NXP website`_. + +Supported Features +================== + +The Zephyr mimx8mp_evk board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/arm/mimx8mp_evk/mimx8mp_evk_defconfig`. + +Other hardware features are not currently supported by the port. + +Connections and IOs +=================== + +MIMX8MP EVK board was tested with the following pinmux controller +configuration. + ++---------------+-----------------+---------------------------+ +| Board Name | SoC Name | Usage | ++===============+=================+===========================+ +| UART4 RXD | UART4_TXD | UART Console | ++---------------+-----------------+---------------------------+ +| UART4 TXD | UART4_RXD | UART Console | ++---------------+-----------------+---------------------------+ + +System Clock +============ + +The M7 Core is configured to run at a 800 MHz clock speed. + +Serial Port +=========== + +The i.MX8M Plus SoC has four UARTs. UART_4 is configured for the console and +the remaining are not used/tested. + +Programming and Debugging +************************* + +The MIMX8MP EVK board doesn't have QSPI flash for the M7, and it needs +to be started by the A53 core. The A53 core is responsible to load the M7 binary +application into the RAM, put the M7 in reset, set the M7 Program Counter and +Stack Pointer, and get the M7 out of reset. The A53 can perform these steps at +bootloader level or after the Linux system has booted. + +The M7 can use up to 3 different RAMs (currently, only two configurations are +supported: ITCM and DDR). These are the memory mapping for A53 and M7: + ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| Region | Cortex-A53 | Cortex-M7 (System Bus) | Cortex-M7 (Code Bus) | Size | ++============+=========================+========================+=======================+======================+ +| OCRAM | 0x00900000-0x0098FFFF | 0x20200000-0x2028FFFF | 0x00900000-0x0098FFFF | 576KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| DTCM | 0x00800000-0x0081FFFF | 0x20000000-0x2001FFFF | | 128KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| ITCM | 0x007E0000-0x007FFFFF | | 0x00000000-0x0001FFFF | 128KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| OCRAM_S | 0x00180000-0x00188FFF | 0x20180000-0x20188FFF | 0x00180000-0x00188FFF | 36KB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ +| DDR | 0x80000000-0x803FFFFF | 0x80200000-0x803FFFFF | 0x80000000-0x801FFFFF | 2MB | ++------------+-------------------------+------------------------+-----------------------+----------------------+ + +For more information about memory mapping see the +`i.MX 8M Plus Applications Processor Reference Manual`_ (section 2.1 to 2.3) + +At compilation time you have to choose which RAM will be used. This +configuration is done based on board name (mimx8mp_evk_itcm for ITCM and +mimx8mp_evk_ddr for DDR). + +Load and run Zephyr on M7 from A53 using u-boot by copying the compiled +``zephyr.bin`` to the first FAT partition of the SD card and plug the SD +card into the board. Power it up and stop the u-boot execution at prompt. + +Load the M7 binary onto the desired memory and start its execution using: + +ITCM +=== + +.. code-block:: console + + fatload mmc 0:1 0x48000000 zephyr.bin + cp.b 0x48000000 0x7e0000 20000 + bootaux 0x7e0000 + +DDR +=== + +.. code-block:: console + + fatload mmc 0:1 0x80000000 zephyr.bin + dcache flush + bootaux 0x80000000 + +Debugging +========= + +MIMX8MP EVK board can be debugged by connecting an external JLink +JTAG debugger to the J24 debug connector and to the PC. Then +the application can be debugged using the usual way. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: mimx8mp_evk_itcm + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build v2.7.99-1310-g2801bf644a91 *** + Hello World! mimx8mp_evk + +References +========== + +.. _NXP website: + https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/evaluation-kit-for-the-i-mx-8m-plus-applications-processor:8MPLUSLPD4-EVK + +.. _i.MX 8M Plus Applications Processor Reference Manual: + https://www.nxp.com/webapp/Download?colCode=IMX8MPRM diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.dts b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.dts new file mode 100644 index 00000000000..575f5a8371b --- /dev/null +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "NXP i.MX8M Plus EVK board"; + compatible = "nxp,mimx8mp_evk"; + + chosen { + /* DDR */ + zephyr,flash = &ddr_code; + zephyr,sram = &ddr_sys; + + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + }; +}; + +&uart4 { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml new file mode 100644 index 00000000000..fc897e4b1e0 --- /dev/null +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr.yaml @@ -0,0 +1,22 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: mimx8mp_evk_ddr +name: NXP i.MX8M Plus EVK (DDR) +type: mcu +arch: arm +ram: 2048 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb + - xtools +testing: + ignore_tags: + - net + - bluetooth +supported: + - uart diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr_defconfig b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr_defconfig new file mode 100644 index 00000000000..9f4a18e6a78 --- /dev/null +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_ddr_defconfig @@ -0,0 +1,17 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_SERIES_IMX8ML_M7=y +CONFIG_SOC_MIMX8ML8=y +CONFIG_BOARD_MIMX8MP_EVK=y +CONFIG_CORTEX_M_SYSTICK=y +CONFIG_CLOCK_CONTROL=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_CONSOLE=y +CONFIG_XIP=y +CONFIG_CODE_DDR=y diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.dts b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.dts new file mode 100644 index 00000000000..b8d3ba0177e --- /dev/null +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "NXP i.MX8M Plus EVK board"; + compatible = "nxp,mimx8mp_evk"; + + chosen { + /* TCM */ + zephyr,flash = &itcm; + zephyr,sram = &dtcm; + + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + }; +}; + +&uart4 { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml new file mode 100644 index 00000000000..ed059c18aed --- /dev/null +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm.yaml @@ -0,0 +1,22 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: mimx8mp_evk_itcm +name: NXP i.MX8M Plus EVK (ITCM) +type: mcu +arch: arm +ram: 128 +flash: 128 +toolchain: + - zephyr + - gnuarmemb + - xtools +testing: + ignore_tags: + - net + - bluetooth +supported: + - uart diff --git a/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm_defconfig b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm_defconfig new file mode 100644 index 00000000000..5298cc33568 --- /dev/null +++ b/boards/arm/mimx8mp_evk/mimx8mp_evk_itcm_defconfig @@ -0,0 +1,17 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_SERIES_IMX8ML_M7=y +CONFIG_SOC_MIMX8ML8=y +CONFIG_BOARD_MIMX8MP_EVK=y +CONFIG_CORTEX_M_SYSTICK=y +CONFIG_CLOCK_CONTROL=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_CONSOLE=y +CONFIG_XIP=y +CONFIG_CODE_ITCM=y diff --git a/boards/arm/mimx8mp_evk/pinmux.c b/boards/arm/mimx8mp_evk/pinmux.c new file mode 100644 index 00000000000..678458553b2 --- /dev/null +++ b/boards/arm/mimx8mp_evk/pinmux.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static int mimx8mp_evk_pinmux_init(const struct device *dev) +{ + ARG_UNUSED(dev); + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay) + IOMUXC_SetPinMux(IOMUXC_UART4_RXD_UART4_RX, 0U); + IOMUXC_SetPinConfig(IOMUXC_UART4_RXD_UART4_RX, + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PE_MASK); + IOMUXC_SetPinMux(IOMUXC_UART4_TXD_UART4_TX, 0U); + IOMUXC_SetPinConfig(IOMUXC_UART4_TXD_UART4_TX, + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PE_MASK); +#endif + + return 0; + +} + +SYS_INIT(mimx8mp_evk_pinmux_init, PRE_KERNEL_1, 0); diff --git a/dts/arm/nxp/nxp_imx8ml_m7.dtsi b/dts/arm/nxp/nxp_imx8ml_m7.dtsi new file mode 100644 index 00000000000..6787781d8ee --- /dev/null +++ b/dts/arm/nxp/nxp_imx8ml_m7.dtsi @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m7"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + arm,num-mpu-regions = <16>; + }; + }; + }; + + soc { + itcm: itcm@0 { + compatible = "nxp,imx-itcm"; + reg = <0x0 DT_SIZE_K(128)>; + }; + + dtcm: dtcm@20000000 { + compatible = "nxp,imx-dtcm"; + reg = <0x20000000 DT_SIZE_K(128)>; + }; + + ocram_code: code@900000 { + compatible = "nxp,imx-code-bus"; + reg = <0x00900000 DT_SIZE_K(576)>; + label = "OCRAM CODE"; + }; + + ocram_sys: memory@20200000 { + device_type = "memory"; + compatible = "nxp,imx-sys-bus"; + reg = <0x20200000 DT_SIZE_K(576)>; + label = "OCRAM SYSTEM"; + }; + + ocram_s_code: code@180000 { + compatible = "nxp,imx-code-bus"; + reg = <0x00180000 DT_SIZE_K(36)>; + label = "OCRAM_S CODE"; + }; + + ocram_s_sys: memory@20180000 { + device_type = "memory"; + compatible = "nxp,imx-sys-bus"; + reg = <0x20180000 DT_SIZE_K(36)>; + label = "OCRAM_S SYSTEM"; + }; + + ddr_code: code@80000000 { + device_type = "memory"; + compatible = "nxp,imx-code-bus"; + reg = <0x80000000 DT_SIZE_M(2)>; + label = "DDR CODE"; + }; + + ddr_sys: memory@80200000 { + device_type = "memory"; + compatible = "nxp,imx-sys-bus"; + reg = <0x80200000 DT_SIZE_M(2)>; + label = "DDR SYSTEM"; + }; + + ccm: ccm@30380000 { + compatible = "nxp,imx-ccm"; + reg = <0x30380000 DT_SIZE_K(64)>; + label = "CCM"; + #clock-cells = <3>; + }; + + /* + * For now only UART4 is supported and + * tested with the serial driver + */ + uart4: uart@30a60000 { + compatible = "nxp,imx-iuart"; + reg = <0x30a60000 0x10000>; + interrupts = <29 3>; + clocks = <&ccm IMX_CCM_UART_CLK 0x6c 24>; + label = "UART_4"; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/include/dt-bindings/rdc/imx_rdc.h b/include/dt-bindings/rdc/imx_rdc.h index be8c6aa8eda..6133101418f 100644 --- a/include/dt-bindings/rdc/imx_rdc.h +++ b/include/dt-bindings/rdc/imx_rdc.h @@ -10,6 +10,7 @@ #define A7_DOMAIN_ID 0 #define A9_DOMAIN_ID 0 #define M4_DOMAIN_ID 1 +#define M7_DOMAIN_ID 1 #define RDC_DOMAIN_PERM_NONE (0x0) #define RDC_DOMAIN_PERM_W (0x1) diff --git a/soc/arm/nxp_imx/Kconfig b/soc/arm/nxp_imx/Kconfig index bd6e1e9531b..434333e9f25 100644 --- a/soc/arm/nxp_imx/Kconfig +++ b/soc/arm/nxp_imx/Kconfig @@ -19,5 +19,6 @@ config SOC_PART_NUMBER default SOC_PART_NUMBER_IMX_6X_M4 if SOC_SERIES_IMX_6X_M4 default SOC_PART_NUMBER_IMX7_M4 if SOC_SERIES_IMX7_M4 default SOC_PART_NUMBER_IMX8MM_M4 if SOC_SERIES_IMX8MM_M4 + default SOC_PART_NUMBER_IMX8ML_M7 if SOC_SERIES_IMX8ML_M7 endif # SOC_FAMILY_IMX diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt b/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt new file mode 100644 index 00000000000..e88ee3356e3 --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2021, Laird Connectivity +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) + +zephyr_sources( + soc.c + mpu_regions.c +) diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 new file mode 100644 index 00000000000..2240ab3c4cb --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7 @@ -0,0 +1,57 @@ +# MIMX8ML8 SoC defconfig + +# Copyright (c) 2021, Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MIMX8ML8 + +config SOC + string + default "mimx8ml8" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + int + default 800000000 + +if CLOCK_CONTROL + +config CLOCK_CONTROL_MCUX_CCM + default y if HAS_MCUX_CCM + +endif # CLOCK_CONTROL + +if PINMUX + +config PINMUX_MCUX + default y + +endif # PINMUX + +if SERIAL + +config UART_MCUX_IUART + default y + +endif # SERIAL + +if CODE_ITCM + +config FLASH_SIZE + default $(dt_node_reg_size_int,/soc/itcm@0,0,K) + +config FLASH_BASE_ADDRESS + default $(dt_node_reg_addr_hex,/soc/itcm@0) + +endif # CODE_ITCM + +if CODE_DDR + +config FLASH_SIZE + default $(dt_node_reg_size_int,/soc/code@80000000,0,K) + +config FLASH_BASE_ADDRESS + default $(dt_node_reg_addr_hex,/soc/code@80000000) + +endif # CODE_DDR + +endif # SOC_MIMX8ML8 diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.series b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.series new file mode 100644 index 00000000000..e95ab9c9595 --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.series @@ -0,0 +1,18 @@ +# i.MX8ML M7 SoC series defconfig + +# Copyright (c) 2021, Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_IMX8ML_M7 + +config SOC_SERIES + default "mimx8ml8_m7" + +config NUM_IRQS + int + # must be >= the highest interrupt number used + default 159 + +source "soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.defconfig.mimx8ml8_m7" + +endif # SOC_SERIES_IMX8ML_M7 diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.series b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.series new file mode 100644 index 00000000000..fc55afd4aae --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.series @@ -0,0 +1,14 @@ +# i.MX8ML M7 core series + +# Copyright (c) 2021, Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_IMX8ML_M7 + bool "i.MX8ML M7 Core Series" + select ARM + select CPU_CORTEX_M7 + select SOC_FAMILY_IMX + select CPU_HAS_FPU + select INIT_VIDEO_PLL + help + Enable support for i.MX8ML M7 MCU series diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.soc b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.soc new file mode 100644 index 00000000000..b638760f731 --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/Kconfig.soc @@ -0,0 +1,48 @@ +# i.MX8ML M7 SoC series + +# Copyright (c) 2021, Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +choice +prompt "i.MX8ML M7 Selection" +depends on SOC_SERIES_IMX8ML_M7 + +config SOC_MIMX8ML8 + bool "SOC_MIMX8ML8" + select HAS_MCUX + select HAS_MCUX_CCM + select HAS_MCUX_RDC + select CPU_HAS_ARM_MPU + select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS + select ARM_MPU + +endchoice + +if SOC_SERIES_IMX8ML_M7 + +config SOC_PART_NUMBER_MIMX8ML8DVNLZ + bool + +config SOC_PART_NUMBER_IMX8ML_M7 + string + default "MIMX8ML8DVNLZ" if SOC_PART_NUMBER_MIMX8ML8DVNLZ + help + This string holds the full part number of the SoC. It is a hidden option + that you should not set directly. The part number selection choice defines + the default value for this string. + +choice CODE_LOCATION + prompt "Code location selection" + +config CODE_ITCM + bool "Link code into internal instruction tightly coupled memory (ITCM)" + +config CODE_DDR + bool "Link code into DDR memory" + +endchoice + +config INIT_VIDEO_PLL + bool "Initialize Video PLL" + +endif # SOC_SERIES_IMX8ML_M7 diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld b/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld new file mode 100644 index 00000000000..2aad0bc22b3 --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/linker.ld @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include + +MEMORY + { +#if defined(CONFIG_CODE_DDR) + DDR (wx) : ORIGIN = 0x80400000, LENGTH = 0x00C00000 +#else + DDR (wx) : ORIGIN = 0x80000000, LENGTH = 0x01000000 +#endif + } + +#include diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c b/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c new file mode 100644 index 00000000000..299c0a23e9e --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/mpu_regions.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "../../common/cortex_m/arm_mpu_mem_cfg.h" + +#define REGION_MASK_BASE_ADDRESS 0x00000000U +#define REGION_ITCM_BASE_ADDRESS 0x00000000U +#define REGION_QSPI_BASE_ADDRESS 0x08000000U +#define REGION_DTCM_BASE_ADDRESS 0x20000000U +#define REGION_DDR_BASE_ADDRESS 0x40000000U +#define REGION_DDR2_BASE_ADDRESS 0x80000000U +#if defined(CONFIG_CODE_DDR) +#define REGION_DDR_NONCACHE_BASE_ADDRESS 0x80000000U +#define REGION_DDR_NONCACHE_SIZE 0x00400000U +#endif + +static const struct arm_mpu_region mpu_regions[] = { + /* + * Region 0 [0x0000_0000 - 0x4000_0000]: + * Memory with Device type, not executable, not shareable, non-cacheable. + */ + MPU_REGION_ENTRY("MASK", REGION_MASK_BASE_ADDRESS, + { ARM_MPU_RASR(1, ARM_MPU_AP_FULL, + 0, 0, 0, 1, 0, ARM_MPU_REGION_SIZE_1GB) }), + + /* + * Region 1 ITCM[0x0000_0000 - 0x0001_FFFF]: + * Memory with Normal type, not shareable, non-cacheable + */ + MPU_REGION_ENTRY("ITCM", REGION_ITCM_BASE_ADDRESS, + { ARM_MPU_RASR(0, ARM_MPU_AP_FULL, + 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_128KB) }), + + /* + * Region 2 QSPI[0x0800_0000 - 0x0FFF_FFFF]: + * Memory with Normal type, not shareable, cacheable + */ + MPU_REGION_ENTRY("QSPI", REGION_QSPI_BASE_ADDRESS, + { ARM_MPU_RASR(0, ARM_MPU_AP_FULL, + 1, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128MB) }), + + /* + * Region 3 DTCM[0x2000_0000 - 0x2002_0000]: + * Memory with Normal type, not shareable, non-cacheable + */ + MPU_REGION_ENTRY("DTCM", REGION_DTCM_BASE_ADDRESS, + { ARM_MPU_RASR(0, ARM_MPU_AP_FULL, + 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_128KB) }), + + /* + * Region 4 DDR[0x4000_0000 - 0x8000_0000]: + * Memory with Normal type, not shareable, non-cacheable + */ + MPU_REGION_ENTRY("DDR", REGION_DDR_BASE_ADDRESS, + { ARM_MPU_RASR(0, ARM_MPU_AP_FULL, + 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB) }), + + /* + * Non-cacheable area is provided in DDR memory, the DDR region [0x80000000 ~ 0x81000000] + * (please see the imx8mp-evk-rpmsg.dts) totally 16MB is revserved for CM7 core. You can put + * global or static uninitialized variables in NonCacheable section(initialized variables in + * NonCacheable.init section) to make them uncacheable. Since the base address of MPU region + * should be multiples of region size, to make it simple, the MPU region 5 set the address + * space 0x80000000 ~ 0xBFFFFFFF to be non-cacheable. Then MPU region 6 set the text and + * data section to be cacheable if the program running on DDR. The cacheable area base + * address should be multiples of its size in linker file, they can be modified per your + * needs. + * + * Region 5 DDR[0x8000_0000 - 0xBFFFFFFF]: + * Memory with Normal type, not shareable, non-cacheable + */ + MPU_REGION_ENTRY("DDR2", REGION_DDR2_BASE_ADDRESS, + { ARM_MPU_RASR(0, ARM_MPU_AP_FULL, + 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB) }), + +#if defined(CONFIG_CODE_DDR) + /* If run on DDR, configure text and data section to be cacheable */ + MPU_REGION_ENTRY("DDR_NONCACHE", REGION_DDR_NONCACHE_BASE_ADDRESS, + { ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, + 0, 1, 1, 0, REGION_DDR_NONCACHE_SIZE) }), +#endif +}; + +const struct arm_mpu_config mpu_config = { + .num_regions = ARRAY_SIZE(mpu_regions), + .mpu_regions = mpu_regions, +}; diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/soc.c b/soc/arm/nxp_imx/mimx8ml8_m7/soc.c new file mode 100644 index 00000000000..48bd9b1c5b8 --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/soc.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* OSC/PLL is already initialized by ROM and Cortex-A53 (u-boot) */ +static void SOC_RdcInit(void) +{ + /* Move M7 core to specific RDC domain 1 */ + rdc_domain_assignment_t assignment = {0}; + uint8_t domainId = 0U; + + domainId = RDC_GetCurrentMasterDomainId(RDC); + /* Only configure the RDC if RDC peripheral write access allowed. */ + if ((0x1U & RDC_GetPeriphAccessPolicy(RDC, kRDC_Periph_RDC, domainId)) != 0U) { + assignment.domainId = M7_DOMAIN_ID; + RDC_SetMasterDomainAssignment(RDC, kRDC_Master_M7, &assignment); + } + + /* + * The M7 core is running at domain 1, now enable the clock gate of the following IP/BUS/PLL + * in domain 1 in the CCM. In this way, to ensure the clock of the peripherals used by M + * core not be affected by A core which is running at domain 0. + */ + CLOCK_EnableClock(kCLOCK_Iomux); + + CLOCK_EnableClock(kCLOCK_Ipmux1); + CLOCK_EnableClock(kCLOCK_Ipmux2); + CLOCK_EnableClock(kCLOCK_Ipmux3); + +#if defined(FLASH_TARGET) + CLOCK_EnableClock(kCLOCK_Qspi); +#endif + + /* Enable the CCGR gate for SysPLL1 in Domain 1 */ + CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll); + /* Enable the CCGR gate for SysPLL2 in Domain 1 */ + CLOCK_ControlGate(kCLOCK_SysPll2Gate, kCLOCK_ClockNeededAll); + /* Enable the CCGR gate for SysPLL3 in Domain 1 */ + CLOCK_ControlGate(kCLOCK_SysPll3Gate, kCLOCK_ClockNeededAll); +#ifdef CONFIG_INIT_VIDEO_PLL + /* Enable the CCGR gate for VideoPLL1 in Domain 1 */ + CLOCK_ControlGate(kCLOCK_VideoPll1Gate, kCLOCK_ClockNeededAll); +#endif +} + +/* Integer PLLs: Fout = (mainDiv * refSel) / (preDiv * 2^ postDiv) */ +/* SYSTEM PLL1 configuration */ +const ccm_analog_integer_pll_config_t g_sysPll1Config = { + .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */ + .mainDiv = 400U, + .preDiv = 3U, + .postDiv = 2U, /*!< SYSTEM PLL1 frequency = 800MHZ */ +}; + +/* SYSTEM PLL2 configuration */ +const ccm_analog_integer_pll_config_t g_sysPll2Config = { + .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */ + .mainDiv = 250U, + .preDiv = 3U, + .postDiv = 1U, /*!< SYSTEM PLL2 frequency = 1000MHZ */ +}; + +/* SYSTEM PLL3 configuration */ +const ccm_analog_integer_pll_config_t g_sysPll3Config = { + .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */ + .mainDiv = 300, + .preDiv = 3U, + .postDiv = 2U, /*!< SYSTEM PLL3 frequency = 600MHZ */ +}; + +static void SOC_ClockInit(void) +{ + /* + * The following steps just show how to configure the PLL clock sources using the clock + * driver on M7 core side . Please note that the ROM has already configured the SYSTEM PLL1 + * to 800Mhz when power up the SOC, meanwhile A core would enable SYSTEM PLL1, SYSTEM PLL2 + * and SYSTEM PLL3 by U-Boot. Therefore, there is no need to configure the system PLL again + * on M7 side, otherwise it would have a risk to make the SOC hang. + */ + + /* switch AHB NOC root to 24M first in order to configure the SYSTEM PLL1. */ + CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxOsc24M); + + /* switch AXI M7 root to 24M first in order to configure the SYSTEM PLL2. */ + CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M); + + /* Set root clock to 800M */ + CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U); + /* switch cortex-m7 to SYSTEM PLL1 */ + CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1); + + /* Set root clock freq to 133M / 1= 133MHZ */ + CLOCK_SetRootDivider(kCLOCK_RootAhb, 1U, 1U); + /* switch AHB to SYSTEM PLL1 DIV6 */ + CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxSysPll1Div6); + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay) && CONFIG_UART_MCUX_IUART + /* Set UART source to SysPLL1 Div10 80MHZ */ + CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10); + /* Set root clock to 80MHZ/ 1= 80MHZ */ + CLOCK_SetRootDivider(kCLOCK_RootUart4, 1U, 1U); +#endif + + CLOCK_EnableClock(kCLOCK_Rdc); /* Enable RDC clock */ + CLOCK_EnableClock(kCLOCK_Ocram); /* Enable Ocram clock */ + + /* The purpose to enable the following modules clock is to make sure the M7 core could work + * normally when A53 core enters the low power status. + */ + CLOCK_EnableClock(kCLOCK_Sim_m); + CLOCK_EnableClock(kCLOCK_Sim_main); + CLOCK_EnableClock(kCLOCK_Sim_s); + CLOCK_EnableClock(kCLOCK_Sim_wakeup); + CLOCK_EnableClock(kCLOCK_Debug); + CLOCK_EnableClock(kCLOCK_Dram); + CLOCK_EnableClock(kCLOCK_Sec_Debug); + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay) && CONFIG_UART_MCUX_IUART + CLOCK_EnableClock(kCLOCK_Uart4); +#endif +} + +static int nxp_mimx8ml8_init(const struct device *arg) +{ + ARG_UNUSED(arg); + + /* SoC specific RDC settings */ + SOC_RdcInit(); + + /* SoC specific Clock settings */ + SOC_ClockInit(); + + return 0; +} + +SYS_INIT(nxp_mimx8ml8_init, PRE_KERNEL_1, 0); diff --git a/soc/arm/nxp_imx/mimx8ml8_m7/soc.h b/soc/arm/nxp_imx/mimx8ml8_m7/soc.h new file mode 100644 index 00000000000..2d6940a6dac --- /dev/null +++ b/soc/arm/nxp_imx/mimx8ml8_m7/soc.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Laird Connectivity + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +/* Add include for DTS generated information */ +#include + +#include + +#endif /* !_ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC__H_ */