From d059a918803a4a791be27071ef6d256a22e77e12 Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Fri, 23 May 2025 18:50:39 +0200 Subject: [PATCH 01/13] west.yml: update modules hal stm32 for stm32mp2x Update west.yml to add the STM32MP2x SoC support in the STM32 HAL. This is done after the merge of the PRs: https://github.com/zephyrproject-rtos/hal_stm32/pull/282 https://github.com/zephyrproject-rtos/hal_stm32/pull/286 Signed-off-by: Youssef Zini --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index f043bcedf7e3..be90e69982d2 100644 --- a/west.yml +++ b/west.yml @@ -245,7 +245,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: 5cbc642b1a79d4f373b1587f8c3027f31bf0d30c + revision: 468e5ad450a75d4baa3eed80e4f77a7700b71203 path: modules/hal/stm32 groups: - hal From 2a6eaca673412b103643b50c0685cac09e93f992 Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Tue, 25 Mar 2025 16:14:27 +0100 Subject: [PATCH 02/13] dts: arm: st: stm32mp25*_m33.dtsi: add init dtsi Add the initial device tree source include (dtsi) files for the stm32mp25 series boards, covering non-secure configuration for zephyr on the Cortex-M33 core. These files provide the basic hardware description, including CPU (Cortex-M33), memory, RCC clock controller and NVIC interrupt controller. Key features: - Set flash and RAM addresses to DDR memory. - Adjust RCC peripheral address for non-secure context. Signed-off-by: Youssef Zini --- dts/arm/st/mp2/stm32mp251_m33.dtsi | 13 +++++++++ dts/arm/st/mp2/stm32mp253_m33.dtsi | 13 +++++++++ dts/arm/st/mp2/stm32mp255_m33.dtsi | 13 +++++++++ dts/arm/st/mp2/stm32mp257_m33.dtsi | 21 +++++++++++++++ dts/arm/st/mp2/stm32mp2_m33.dtsi | 43 ++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 dts/arm/st/mp2/stm32mp251_m33.dtsi create mode 100644 dts/arm/st/mp2/stm32mp253_m33.dtsi create mode 100644 dts/arm/st/mp2/stm32mp255_m33.dtsi create mode 100644 dts/arm/st/mp2/stm32mp257_m33.dtsi create mode 100644 dts/arm/st/mp2/stm32mp2_m33.dtsi diff --git a/dts/arm/st/mp2/stm32mp251_m33.dtsi b/dts/arm/st/mp2/stm32mp251_m33.dtsi new file mode 100644 index 000000000000..4aa157d50e76 --- /dev/null +++ b/dts/arm/st/mp2/stm32mp251_m33.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32mp251", "st,stm32mp2", "simple-bus"; + }; +}; diff --git a/dts/arm/st/mp2/stm32mp253_m33.dtsi b/dts/arm/st/mp2/stm32mp253_m33.dtsi new file mode 100644 index 000000000000..710b68254962 --- /dev/null +++ b/dts/arm/st/mp2/stm32mp253_m33.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32mp253", "st,stm32mp2", "simple-bus"; + }; +}; diff --git a/dts/arm/st/mp2/stm32mp255_m33.dtsi b/dts/arm/st/mp2/stm32mp255_m33.dtsi new file mode 100644 index 000000000000..65fc830c7dd3 --- /dev/null +++ b/dts/arm/st/mp2/stm32mp255_m33.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32mp255", "st,stm32mp2", "simple-bus"; + }; +}; diff --git a/dts/arm/st/mp2/stm32mp257_m33.dtsi b/dts/arm/st/mp2/stm32mp257_m33.dtsi new file mode 100644 index 000000000000..95c729b1910e --- /dev/null +++ b/dts/arm/st/mp2/stm32mp257_m33.dtsi @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + ddr_code: memory0@80100000 { + reg = <0x80100000 DT_SIZE_M(8)>; + }; + + ddr_sys: memory1@80a00000 { + reg = <0x80a00000 DT_SIZE_M(8)>; + }; + + soc { + compatible = "st,stm32mp257", "st,stm32mp2", "simple-bus"; + }; +}; diff --git a/dts/arm/st/mp2/stm32mp2_m33.dtsi b/dts/arm/st/mp2/stm32mp2_m33.dtsi new file mode 100644 index 000000000000..c463ca566b95 --- /dev/null +++ b/dts/arm/st/mp2/stm32mp2_m33.dtsi @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m33"; + reg = <0>; + }; + }; + + ddr_code: memory0@80100000 { + compatible = "mmio-sram"; + }; + + ddr_sys: memory1@80a00000 { + compatible = "mmio-sram"; + }; + + soc { + rcc: rcc@44200000 { + compatible = "st,stm32mp2-rcc"; + clocks-controller; + #clock-cells = <2>; + reg = <0x44200000 DT_SIZE_K(64)>; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; From 32ddc02bf08ee130bc0d94b86758dd7c8660794f Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Fri, 28 Mar 2025 13:43:08 +0100 Subject: [PATCH 03/13] soc: stm32: add initial soc support for stm32mp2x Add initial soc support for the stm32mp2x series, including initial Kconfig entries and default configuration files. This enables Zephyr to recognize and build for the stm32mp2x series, taking the stm32mp257f_ev1 as a baseline. Includes: - Kconfig and defconfig files for SoC selection and defaults - soc.h for hal headers - CMakeLists.txt for build system integration - soc.yml update to register the new SoC System Clock is configured statically from DTS. So no initialization hook or soc.c needed. Signed-off-by: Youssef Zini --- soc/st/stm32/soc.yml | 5 ++++ soc/st/stm32/stm32mp2x/CMakeLists.txt | 9 +++++++ soc/st/stm32/stm32mp2x/Kconfig | 17 +++++++++++++ soc/st/stm32/stm32mp2x/Kconfig.defconfig | 10 ++++++++ .../stm32mp2x/Kconfig.defconfig.stm32mp257fxx | 11 ++++++++ soc/st/stm32/stm32mp2x/Kconfig.soc | 18 +++++++++++++ soc/st/stm32/stm32mp2x/m33/CMakeLists.txt | 7 ++++++ soc/st/stm32/stm32mp2x/m33/soc.h | 25 +++++++++++++++++++ 8 files changed, 102 insertions(+) create mode 100644 soc/st/stm32/stm32mp2x/CMakeLists.txt create mode 100644 soc/st/stm32/stm32mp2x/Kconfig create mode 100644 soc/st/stm32/stm32mp2x/Kconfig.defconfig create mode 100644 soc/st/stm32/stm32mp2x/Kconfig.defconfig.stm32mp257fxx create mode 100644 soc/st/stm32/stm32mp2x/Kconfig.soc create mode 100644 soc/st/stm32/stm32mp2x/m33/CMakeLists.txt create mode 100644 soc/st/stm32/stm32mp2x/m33/soc.h diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index 705097b35782..a3f781c3beed 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -193,6 +193,11 @@ family: - name: stm32mp13x socs: - name: stm32mp135fxx + - name: stm32mp2x + socs: + - name: stm32mp257fxx + cpuclusters: + - name: m33 - name: stm32n6x socs: - name: stm32n657xx diff --git a/soc/st/stm32/stm32mp2x/CMakeLists.txt b/soc/st/stm32/stm32mp2x/CMakeLists.txt new file mode 100644 index 000000000000..fdfdc3244a73 --- /dev/null +++ b/soc/st/stm32/stm32mp2x/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) + +if(CONFIG_CPU_CORTEX_M33) + add_subdirectory(m33) +endif() diff --git a/soc/st/stm32/stm32mp2x/Kconfig b/soc/st/stm32/stm32mp2x/Kconfig new file mode 100644 index 000000000000..016ee4ad2072 --- /dev/null +++ b/soc/st/stm32/stm32mp2x/Kconfig @@ -0,0 +1,17 @@ +# STMicroelectronics STM32MP2 MPU series +# +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32MP2X + select ARM + select CPU_HAS_FPU + select HAS_STM32CUBE + +config SOC_STM32MP2X_M33 + select ARMV8_M_DSP + select ARM_TRUSTZONE_M + select CPU_CORTEX_M33 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_ARM_MPU + select CPU_HAS_ARM_SAU diff --git a/soc/st/stm32/stm32mp2x/Kconfig.defconfig b/soc/st/stm32/stm32mp2x/Kconfig.defconfig new file mode 100644 index 000000000000..144368d8e1bd --- /dev/null +++ b/soc/st/stm32/stm32mp2x/Kconfig.defconfig @@ -0,0 +1,10 @@ +# STMicroelectronics STM32MP2 MPU series +# +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_STM32MP2X + +rsource "Kconfig.defconfig.stm32mp2*" + +endif # SOC_SERIES_STM32MP2X diff --git a/soc/st/stm32/stm32mp2x/Kconfig.defconfig.stm32mp257fxx b/soc/st/stm32/stm32mp2x/Kconfig.defconfig.stm32mp257fxx new file mode 100644 index 000000000000..57a77780ee9b --- /dev/null +++ b/soc/st/stm32/stm32mp2x/Kconfig.defconfig.stm32mp257fxx @@ -0,0 +1,11 @@ +# STMicroelectronics STM32MP2 MPU series +# +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32MP2X_M33 + +config NUM_IRQS + default 320 + +endif # SOC_STM32MP2X_M33 diff --git a/soc/st/stm32/stm32mp2x/Kconfig.soc b/soc/st/stm32/stm32mp2x/Kconfig.soc new file mode 100644 index 000000000000..92825e7a0c56 --- /dev/null +++ b/soc/st/stm32/stm32mp2x/Kconfig.soc @@ -0,0 +1,18 @@ +# STMicroelectronics STM32MP2 MPU series +# +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32MP2X + bool + select SOC_FAMILY_STM32 + +config SOC_SERIES + default "stm32mp2x" if SOC_SERIES_STM32MP2X + +config SOC_STM32MP2X_M33 + bool + select SOC_SERIES_STM32MP2X + +config SOC + default "stm32mp257fxx" if SOC_STM32MP2X_M33 diff --git a/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt b/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt new file mode 100644 index 000000000000..2ef552ce5aca --- /dev/null +++ b/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) + +zephyr_include_directories(.) diff --git a/soc/st/stm32/stm32mp2x/m33/soc.h b/soc/st/stm32/stm32mp2x/m33/soc.h new file mode 100644 index 000000000000..c517d443c676 --- /dev/null +++ b/soc/st/stm32/stm32mp2x/m33/soc.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the STM32MP2 family processors. + * + * Based on reference manual: + * STM32MP23/25xx advanced ARM(r)-based 32/64-bit MPUs + * + * Chapter 2.4.2: Memory map and register boundary addresses + */ + +#ifndef _STM32MP2_M33_SOC_H_ +#define _STM32MP2_M33_SOC_H_ + +#ifndef _ASMLANGUAGE + +#include + +#endif /* !_ASMLANGUAGE */ + +#endif /* !_STM32MP2_M33_SOC_H_ */ From 7c2b110abd7e1ba5b3d3ae9f6f9e5fb0f42d16ab Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Tue, 22 Apr 2025 14:38:47 +0200 Subject: [PATCH 04/13] soc: linker.ld: add linker script for stm32mp2x Add a linker script for the stm32mp2x soc series. It includes the standard arm cortex-m linker and adds standard zephyr relocation sections. Replace the rom_start section name with .isr_vectors in the linker script. This is necessary for the zephyr firmware to be started by the remote proc driver which expects the section containing the vector table to be named .isr_vectors. Signed-off-by: Youssef Zini --- soc/st/stm32/stm32mp2x/m33/CMakeLists.txt | 2 ++ soc/st/stm32/stm32mp2x/m33/linker.ld | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 soc/st/stm32/stm32mp2x/m33/linker.ld diff --git a/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt b/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt index 2ef552ce5aca..1b3edbb52211 100644 --- a/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt +++ b/soc/st/stm32/stm32mp2x/m33/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/st/stm32/stm32mp2x/m33/linker.ld b/soc/st/stm32/stm32mp2x/m33/linker.ld new file mode 100644 index 000000000000..6b963d31e93b --- /dev/null +++ b/soc/st/stm32/stm32mp2x/m33/linker.ld @@ -0,0 +1,21 @@ +/* linker.ld - Linker command/script file */ + +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define rom_start .isr_vectors + +#include + +SECTIONS +{ + /* Standard Zephyr relocation section */ +#include + +#ifdef CONFIG_LLEXT +#include +#endif +} From 4da74b4facb3581575950d1099d2d5d7bf06da97 Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Fri, 28 Mar 2025 15:19:33 +0100 Subject: [PATCH 05/13] boards: st: add support for stm32mp257f_ev1 board Introduce initial board support for the STM32MP257F-EV1. This includes: - Board metadata (board.yml, stm32mp257f_ev1.yaml) - Base software configuration (Kconfig.stm32mp257f_ev1) - CMake build integration (board.cmake) - Default configuration (stm32mp257f_ev1_stm32mp257fxx_m33_defconfig) - Minimal device tree (stm32mp257f_ev1_stm32mp257fxx_m33.dts) - Initial documentation and image for the stm32mp257f_ev1 board. - OpenOCD configuration files for debugging support. This enables the STM32MP257F-EV1 board to build and debug a hello world sample. Note that other necessary openocd configuration files are added to the zephyr sdk directory and can be found in the stm-openocd repository[1]. [1]:https://github.com/STMicroelectronics/device-stm-openocd/tree/main Signed-off-by: Youssef Zini --- .../stm32mp257f_ev1/Kconfig.stm32mp257f_ev1 | 5 + boards/st/stm32mp257f_ev1/board.cmake | 9 + boards/st/stm32mp257f_ev1/board.yml | 6 + .../doc/img/stm32mp257f_ev1.webp | Bin 0 -> 35476 bytes boards/st/stm32mp257f_ev1/doc/index.rst | 250 ++++++++++++++++++ .../stm32mp257f_ev1_stm32mp257fxx_m33.dts | 22 ++ .../stm32mp257f_ev1_stm32mp257fxx_m33.yaml | 24 ++ ...tm32mp257f_ev1_stm32mp257fxx_m33_defconfig | 10 + .../support/openocd_stm32mp257f_ev1_m33.cfg | 10 + 9 files changed, 336 insertions(+) create mode 100644 boards/st/stm32mp257f_ev1/Kconfig.stm32mp257f_ev1 create mode 100644 boards/st/stm32mp257f_ev1/board.cmake create mode 100644 boards/st/stm32mp257f_ev1/board.yml create mode 100644 boards/st/stm32mp257f_ev1/doc/img/stm32mp257f_ev1.webp create mode 100644 boards/st/stm32mp257f_ev1/doc/index.rst create mode 100644 boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.dts create mode 100644 boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.yaml create mode 100644 boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig create mode 100644 boards/st/stm32mp257f_ev1/support/openocd_stm32mp257f_ev1_m33.cfg diff --git a/boards/st/stm32mp257f_ev1/Kconfig.stm32mp257f_ev1 b/boards/st/stm32mp257f_ev1/Kconfig.stm32mp257f_ev1 new file mode 100644 index 000000000000..5184ef6636ed --- /dev/null +++ b/boards/st/stm32mp257f_ev1/Kconfig.stm32mp257f_ev1 @@ -0,0 +1,5 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32MP257F_EV1 + select SOC_STM32MP2X_M33 if BOARD_STM32MP257F_EV1_STM32MP257FXX_M33 diff --git a/boards/st/stm32mp257f_ev1/board.cmake b/boards/st/stm32mp257f_ev1/board.cmake new file mode 100644 index 000000000000..eb52f9981fef --- /dev/null +++ b/boards/st/stm32mp257f_ev1/board.cmake @@ -0,0 +1,9 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_BOARD_STM32MP257F_EV1_STM32MP257FXX_M33) + board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_stm32mp257f_ev1_m33.cfg") + board_runner_args(openocd "--gdb-init=target extended-remote :3334") +endif() + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/st/stm32mp257f_ev1/board.yml b/boards/st/stm32mp257f_ev1/board.yml new file mode 100644 index 000000000000..81cdba090642 --- /dev/null +++ b/boards/st/stm32mp257f_ev1/board.yml @@ -0,0 +1,6 @@ +board: + name: stm32mp257f_ev1 + full_name: STM32MP257F-EV1 Evaluation Board + vendor: st + socs: + - name: stm32mp257fxx diff --git a/boards/st/stm32mp257f_ev1/doc/img/stm32mp257f_ev1.webp b/boards/st/stm32mp257f_ev1/doc/img/stm32mp257f_ev1.webp new file mode 100644 index 0000000000000000000000000000000000000000..ad2c6e8dd776f1634f741d840c81e1612fc3bfe8 GIT binary patch literal 35476 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 >yN?Q*F!9lz53=Zd~ZT65iMrMv=Z>b^Etp_sC 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 + +/ { + model = "STMicroelectronics STM32MP257F-EV1 board"; + compatible = "st,stm32mp257f-ev1", "st,stm32mp25"; + + chosen { + zephyr,flash = &ddr_code; + zephyr,sram = &ddr_sys; + }; +}; + +&rcc { + clock-frequency = ; +}; diff --git a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.yaml b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.yaml new file mode 100644 index 000000000000..127e2f85d8b3 --- /dev/null +++ b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.yaml @@ -0,0 +1,24 @@ +identifier: stm32mp257f_ev1/stm32mp257fxx/m33 +name: STM32MP257F_EV1 +type: mcu +arch: arm +toolchain: + - zephyr + - gccarmemb +supported: + - LED + - gpio +testing: + ignore_tags: + - cmsis_rtos_v2 + - net + - mpu + - tinycrypt + - crypto + - aes + - cmm + - shell + - nfc +ram: 8192 +flash: 8192 +vendor: st diff --git a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig new file mode 100644 index 000000000000..a400e52c0cde --- /dev/null +++ b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig @@ -0,0 +1,10 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +CONFIG_CLOCK_CONTROL=n + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/st/stm32mp257f_ev1/support/openocd_stm32mp257f_ev1_m33.cfg b/boards/st/stm32mp257f_ev1/support/openocd_stm32mp257f_ev1_m33.cfg new file mode 100644 index 000000000000..a690cfa54995 --- /dev/null +++ b/boards/st/stm32mp257f_ev1/support/openocd_stm32mp257f_ev1_m33.cfg @@ -0,0 +1,10 @@ +# Only enable the Cortex-M33 debugger +set EN_CA35_0 0 +set EN_CA35_1 0 +set EN_CM33 1 +set EN_CM0P 0 + +source [find board/stm32mp25x_dk.cfg] + +# Set active target to Cortex-M33 +targets stm32mp25x.m33 From 43e0e288635935d19cb3e4d082cec94f8af0e62c Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Wed, 11 Jun 2025 14:38:00 +0200 Subject: [PATCH 06/13] drivers: interrupt_controller: change dt macro Replace the use of `DT_NODELABEL(exti)` which depends on the node label with the defined EXTI_NODE macro using the instance with the `st_stm32_exti` compatible. Since both macros point to the same node, this change doesn't affect the code logic, but makes it independent of the node label, in preparation for the addition of the STM32MP2 exti nodes. Signed-off-by: Youssef Zini --- drivers/interrupt_controller/intc_exti_stm32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/interrupt_controller/intc_exti_stm32.c b/drivers/interrupt_controller/intc_exti_stm32.c index f83fbf9b4e1b..7c4732652431 100644 --- a/drivers/interrupt_controller/intc_exti_stm32.c +++ b/drivers/interrupt_controller/intc_exti_stm32.c @@ -35,7 +35,7 @@ struct stm32_exti_range { uint8_t len; }; -#define NUM_EXTI_LINES DT_PROP(DT_NODELABEL(exti), num_lines) +#define NUM_EXTI_LINES DT_PROP(EXTI_NODE, num_lines) static IRQn_Type exti_irq_table[NUM_EXTI_LINES] = {[0 ... NUM_EXTI_LINES - 1] = 0xFF}; @@ -220,7 +220,7 @@ static int stm32_exti_init(const struct device *dev) { ARG_UNUSED(dev); - DT_FOREACH_PROP_ELEM(DT_NODELABEL(exti), + DT_FOREACH_PROP_ELEM(EXTI_NODE, interrupt_names, STM32_EXTI_INIT_LINE_RANGE); From bab6285b753e0ec24aad85e11562436cb24072c5 Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Tue, 22 Apr 2025 12:19:45 +0200 Subject: [PATCH 07/13] drivers: interrupt_controller: add stm32mp2 exti Add the mp2 exti2 dts to the dtsi file. Add mp2 exti hal and ll function calls with EXTI2 instance. We use the EXTI2 instance because it contains the GPIO interrupts in the non-secure context. (We are trying to build the blinky sample as a first milestone) Signed-off-by: Youssef Zini --- .../interrupt_controller/intc_exti_stm32.c | 37 ++++++++++++++++++- dts/arm/st/mp2/stm32mp2_m33.dtsi | 21 +++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/interrupt_controller/intc_exti_stm32.c b/drivers/interrupt_controller/intc_exti_stm32.c index 7c4732652431..bd6e4418bca2 100644 --- a/drivers/interrupt_controller/intc_exti_stm32.c +++ b/drivers/interrupt_controller/intc_exti_stm32.c @@ -2,6 +2,7 @@ * Copyright (c) 2016 Open-RnD Sp. z o.o. * Copyright (c) 2017 RnDity Sp. z o.o. * Copyright (c) 2019-23 Linaro Limited + * Copyright (C) 2025 Savoir-faire Linux, Inc. * * SPDX-License-Identifier: Apache-2.0 */ @@ -60,7 +61,8 @@ static inline uint32_t stm32_exti_linenum_to_src_cfg_line(gpio_pin_t linenum) #if defined(CONFIG_SOC_SERIES_STM32L0X) || \ defined(CONFIG_SOC_SERIES_STM32F0X) return ((linenum % 4 * 4) << 16) | (linenum / 4); -#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) || \ + defined(CONFIG_SOC_SERIES_STM32MP2X) return ((linenum & 0x3) << (16 + 3)) | (linenum >> 2); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) /* Gives the LL_SBS_EXTI_LINEn corresponding to the line number */ @@ -82,6 +84,9 @@ static inline int stm32_exti_is_pending(stm32_gpio_irq_line_t line) LL_EXTI_IsActiveFallingFlag_0_31(line)); #elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) return LL_C2_EXTI_IsActiveFlag_0_31(line); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) + return LL_EXTI_IsActiveRisingFlag_0_31(EXTI2, line) || + LL_EXTI_IsActiveFallingFlag_0_31(EXTI2, line); #else return LL_EXTI_IsActiveFlag_0_31(line); #endif @@ -99,6 +104,9 @@ static inline void stm32_exti_clear_pending(stm32_gpio_irq_line_t line) LL_EXTI_ClearFallingFlag_0_31(line); #elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) LL_C2_EXTI_ClearFlag_0_31(line); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) + LL_EXTI_ClearRisingFlag_0_31(EXTI2, line); + LL_EXTI_ClearFallingFlag_0_31(EXTI2, line); #else LL_EXTI_ClearFlag_0_31(line); #endif @@ -269,6 +277,8 @@ void stm32_gpio_intc_enable_line(stm32_gpio_irq_line_t line) /* Enable requested line interrupt */ #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) LL_C2_EXTI_EnableIT_0_31(line); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) + LL_C2_EXTI_EnableIT_0_31(EXTI2, line); #else LL_EXTI_EnableIT_0_31(line); #endif @@ -281,6 +291,8 @@ void stm32_gpio_intc_disable_line(stm32_gpio_irq_line_t line) { #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) LL_C2_EXTI_DisableIT_0_31(line); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) + LL_C2_EXTI_DisableIT_0_31(EXTI2, line); #else LL_EXTI_DisableIT_0_31(line); #endif @@ -291,6 +303,24 @@ void stm32_gpio_intc_select_line_trigger(stm32_gpio_irq_line_t line, uint32_t tr z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY); switch (trg) { +#if defined(CONFIG_SOC_SERIES_STM32MP2X) + case STM32_GPIO_IRQ_TRIG_NONE: + LL_EXTI_DisableRisingTrig_0_31(EXTI2, line); + LL_EXTI_DisableFallingTrig_0_31(EXTI2, line); + break; + case STM32_GPIO_IRQ_TRIG_RISING: + LL_EXTI_EnableRisingTrig_0_31(EXTI2, line); + LL_EXTI_DisableFallingTrig_0_31(EXTI2, line); + break; + case STM32_GPIO_IRQ_TRIG_FALLING: + LL_EXTI_EnableFallingTrig_0_31(EXTI2, line); + LL_EXTI_DisableRisingTrig_0_31(EXTI2, line); + break; + case STM32_GPIO_IRQ_TRIG_BOTH: + LL_EXTI_EnableRisingTrig_0_31(EXTI2, line); + LL_EXTI_EnableFallingTrig_0_31(EXTI2, line); + break; +#else /* CONFIG_SOC_SERIES_STM32MP2X */ case STM32_GPIO_IRQ_TRIG_NONE: LL_EXTI_DisableRisingTrig_0_31(line); LL_EXTI_DisableFallingTrig_0_31(line); @@ -307,6 +337,7 @@ void stm32_gpio_intc_select_line_trigger(stm32_gpio_irq_line_t line, uint32_t tr LL_EXTI_EnableRisingTrig_0_31(line); LL_EXTI_EnableFallingTrig_0_31(line); break; +#endif /* CONFIG_SOC_SERIES_STM32MP2X */ default: __ASSERT_NO_MSG(0); break; @@ -369,6 +400,8 @@ void stm32_exti_set_line_src_port(gpio_pin_t line, uint32_t port) LL_EXTI_SetEXTISource(port, ll_line); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) LL_SBS_SetEXTISource(port, ll_line); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) + LL_EXTI_SetEXTISource(EXTI2, port, ll_line); #else LL_SYSCFG_SetEXTISource(port, ll_line); #endif @@ -386,6 +419,8 @@ uint32_t stm32_exti_get_line_src_port(gpio_pin_t line) port = LL_EXTI_GetEXTISource(ll_line); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) port = LL_SBS_GetEXTISource(ll_line); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) + port = LL_EXTI_GetEXTISource(EXTI2, ll_line); #else port = LL_SYSCFG_GetEXTISource(ll_line); #endif diff --git a/dts/arm/st/mp2/stm32mp2_m33.dtsi b/dts/arm/st/mp2/stm32mp2_m33.dtsi index c463ca566b95..3c53fd6676b6 100644 --- a/dts/arm/st/mp2/stm32mp2_m33.dtsi +++ b/dts/arm/st/mp2/stm32mp2_m33.dtsi @@ -35,6 +35,27 @@ #clock-cells = <2>; reg = <0x44200000 DT_SIZE_K(64)>; }; + + exti2: interrupt-controller@46230000 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + reg = <0x46230000 DT_SIZE_K(1)>; + num-lines = <16>; + interrupts = <17 0>, <18 0>, <19 0>, <20 0>, + <21 0>, <22 0>, <23 0>, <24 0>, + <25 0>, <26 0>, <27 0>, <28 0>, + <29 0>, <30 0>, <31 0>, <32 0>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5", "line6", "line7", + "line8", "line9", "line10", "line11", + "line12", "line13", "line14", "line15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 1>, <6 1>, <7 1>, + <8 1>, <9 1>, <10 1>, <11 1>, + <12 1>, <13 1>, <14 1>, <15 1>; + }; }; }; From b3b3f778bd37342183456aa33133cd70ec97db64 Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Fri, 13 Jun 2025 13:35:28 +0200 Subject: [PATCH 08/13] drivers: hwinfo_stm32.c: add support for stm32mp2 Add support for STM32MP2 series in the hwinfo driver. The STM32MP2 series uses the HAL functions since it doesn't have a ll_utils. Signed-off-by: Youssef Zini --- drivers/hwinfo/hwinfo_stm32.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/hwinfo/hwinfo_stm32.c b/drivers/hwinfo/hwinfo_stm32.c index 1d4a1fed0a0f..c29bb3a36da7 100644 --- a/drivers/hwinfo/hwinfo_stm32.c +++ b/drivers/hwinfo/hwinfo_stm32.c @@ -15,7 +15,8 @@ #include #include -#if defined(CONFIG_SOC_SERIES_STM32MP13X) +#if defined(CONFIG_SOC_SERIES_STM32MP13X) \ + || defined(CONFIG_SOC_SERIES_STM32MP2X) /* No ll_utils for the stm32mp13x series, instead use the HAL functions */ /* zephyr-keep-sorted-start */ @@ -32,7 +33,7 @@ #define STM32_UID_WORD_2 LL_GetUID_Word0() /* zephyr-keep-sorted-stop */ -#endif /* CONFIG_SOC_SERIES_STM32MP13X */ +#endif /* CONFIG_SOC_SERIES_STM32MP13X || CONFIG_SOC_SERIES_STM32MP2X */ struct stm32_uid { uint32_t id[3]; @@ -171,6 +172,10 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) if (LL_PWR_MPU_IsActiveFlag_SB()) { flags |= RESET_LOW_POWER_WAKE; } +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) && defined(PWR_FLAG_SB) + if (LL_PWR_HasSystemBeenInStandby()) { + flags |= RESET_LOW_POWER_WAKE; + } #elif defined(CONFIG_SOC_SERIES_STM32WLX) || defined(CONFIG_SOC_SERIES_STM32WBX) if (LL_PWR_IsActiveFlag_C1SB()) { flags |= RESET_LOW_POWER_WAKE; @@ -200,6 +205,8 @@ int z_impl_hwinfo_clear_reset_cause(void) LL_PWR_ClearFlag_MCU(); #elif defined(CONFIG_SOC_SERIES_STM32MP13X) LL_PWR_ClearFlag_MPU(); +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) && defined(PWR_FLAG_SB) + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); #elif defined(CONFIG_SOC_SERIES_STM32WLX) || defined(CONFIG_SOC_SERIES_STM32WBX) LL_PWR_ClearFlag_C1STOP_C1STB(); #elif defined(CONFIG_SOC_SERIES_STM32U0X) && defined(PWR_FLAG_SB) From f235c04dc1e8a9f1eecb27163c58572c1c5a3e79 Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Tue, 22 Apr 2025 13:42:07 +0200 Subject: [PATCH 09/13] dts: clock_control: add mp2 rcc binding Introduce DeviceTree binding for the STM32MP2 RCC clock controller, enabling support for STM32MP2-specific clock configuration in Zephyr. Update Kconfig.stm32 to add a dependency on STM32MP2 configuration, allowing the use of STM32 LL RCC features when targeting STM32MP2 devices. Add header for STM32MP2 per peripheral clock definitions. Signed-off-by: Youssef Zini --- ...tm32mp257f_ev1_stm32mp257fxx_m33_defconfig | 2 - drivers/clock_control/Kconfig.stm32 | 6 ++- dts/bindings/clock/st,stm32mp2-rcc.yaml | 33 ++++++++++++++ .../zephyr/dt-bindings/clock/stm32mp2_clock.h | 45 +++++++++++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 dts/bindings/clock/st,stm32mp2-rcc.yaml create mode 100644 include/zephyr/dt-bindings/clock/stm32mp2_clock.h diff --git a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig index a400e52c0cde..0fdf892fff35 100644 --- a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig +++ b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig @@ -4,7 +4,5 @@ # Enable MPU CONFIG_ARM_MPU=y -CONFIG_CLOCK_CONTROL=n - # Enable HW stack protection CONFIG_HW_STACK_PROTECTION=y diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index d1b41416fdb1..0815e149de68 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -2,6 +2,7 @@ # Copyright (c) 2017 Linaro # Copyright (c) 2017 RnDity Sp. z o.o. +# Copyright (C) 2025 Savoir-faire Linux, Inc. # SPDX-License-Identifier: Apache-2.0 menuconfig CLOCK_CONTROL_STM32_CUBE @@ -9,8 +10,9 @@ menuconfig CLOCK_CONTROL_STM32_CUBE depends on SOC_FAMILY_STM32 default y select USE_STM32_LL_UTILS - select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32MP13X || SOC_SERIES_STM32H7X || \ - SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || \ + select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32MP13X || \ + SOC_SERIES_STM32MP2X || SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || \ + SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32N6X) select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ $(dt_nodelabel_bool_prop,clk_hse,css-enabled)) diff --git a/dts/bindings/clock/st,stm32mp2-rcc.yaml b/dts/bindings/clock/st,stm32mp2-rcc.yaml new file mode 100644 index 000000000000..8bff60a5e332 --- /dev/null +++ b/dts/bindings/clock/st,stm32mp2-rcc.yaml @@ -0,0 +1,33 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32MP2 RCC (Reset and Clock controller). + + On STM32MP2 platforms, the clock tree is configured by the Cortex-A35 core. + As a consequence, the only property to be set in devicetree node is the + clock-frequency. + + As for the peripherals, the clocks are configured per peripheral in the + corresponding device tree node. The clock controller is responsible for + enabling/disabling the clocks for the peripherals, when allowed by the + Resource Isolation Framework(RIF) peripheral, configured by the cortex-A35 + core. + + To declare a peripheral "PERx" clock in the dtsi, you can follow the example + below: + PERx { + ... + clocks = <&rcc STM32_CLOCK(PERx, STM32_CLK)>; + ... + }; + +compatible: "st,stm32mp2-rcc" + +include: + - name: st,stm32-rcc.yaml + property-blocklist: + - ahb-prescaler + - apb1-prescaler + - apb2-prescaler + - undershoot-prevention diff --git a/include/zephyr/dt-bindings/clock/stm32mp2_clock.h b/include/zephyr/dt-bindings/clock/stm32mp2_clock.h new file mode 100644 index 000000000000..8ccffd5e2c70 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32mp2_clock.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32MP2_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32MP2_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/* Undefine the common clocks macro */ +#undef STM32_CLOCK + +/** + * Pack RCC clock register offset and bit in two 32-bit values + * as expected for the Device Tree `clocks` property on STM32. + * + * @param per STM32 Peripheral name (expands to STM32_CLOCK_PERIPH_{PER}) + * @param bit Clock bit + */ +#define STM32_CLOCK(per, bit) (STM32_CLOCK_PERIPH_##per) (1 << bit) + +/* Clock reg */ +#define STM32_CLK 1U +#define STM32_LP_CLK 2U + +/* GPIO Peripheral */ +#define STM32_CLOCK_PERIPH_GPIOA 0x52C +#define STM32_CLOCK_PERIPH_GPIOB 0x530 +#define STM32_CLOCK_PERIPH_GPIOC 0x534 +#define STM32_CLOCK_PERIPH_GPIOD 0x538 +#define STM32_CLOCK_PERIPH_GPIOE 0x53C +#define STM32_CLOCK_PERIPH_GPIOF 0x540 +#define STM32_CLOCK_PERIPH_GPIOG 0x544 +#define STM32_CLOCK_PERIPH_GPIOH 0x548 +#define STM32_CLOCK_PERIPH_GPIOI 0x54C +#define STM32_CLOCK_PERIPH_GPIOJ 0x550 +#define STM32_CLOCK_PERIPH_GPIOK 0x554 +#define STM32_CLOCK_PERIPH_GPIOZ 0x558 + +#define STM32_CLOCK_PERIPH_MIN STM32_CLOCK_PERIPH_GPIOA +#define STM32_CLOCK_PERIPH_MAX STM32_CLOCK_PERIPH_GPIOZ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32MP2_CLOCK_H_ */ From c2041820800e6dd2fe8a42c82a1a5bbded27e9dd Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Tue, 22 Apr 2025 13:42:07 +0200 Subject: [PATCH 10/13] drivers: clock_control: add mp2 clock driver Add the stm32mp2 clock driver to the clock_control subsystem. The driver is a reduced version of the generic stm32 clock driver. Signed-off-by: Youssef Zini --- drivers/clock_control/CMakeLists.txt | 2 + drivers/clock_control/clock_stm32_ll_mp2.c | 72 +++++++++++++++++++ .../clock_control/stm32_clock_control.h | 2 + 3 files changed, 76 insertions(+) create mode 100644 drivers/clock_control/clock_stm32_ll_mp2.c diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 886c92b63578..677eccd9e8ba 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -70,6 +70,8 @@ if(CONFIG_SOC_SERIES_STM32MP1X) zephyr_library_sources(clock_stm32_ll_mp1.c) elseif(CONFIG_SOC_SERIES_STM32MP13X) zephyr_library_sources(clock_stm32_ll_mp13.c) +elseif(CONFIG_SOC_SERIES_STM32MP2X) + zephyr_library_sources(clock_stm32_ll_mp2.c) elseif(CONFIG_SOC_SERIES_STM32H7X) zephyr_library_sources(clock_stm32_ll_h7.c) elseif(CONFIG_SOC_SERIES_STM32H7RSX) diff --git a/drivers/clock_control/clock_stm32_ll_mp2.c b/drivers/clock_control/clock_stm32_ll_mp2.c new file mode 100644 index 000000000000..0164c67a9e00 --- /dev/null +++ b/drivers/clock_control/clock_stm32_ll_mp2.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2025 Savoir-faire Linux, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +static int stm32_clock_control_on(const struct device *dev, clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *) sub_system; + + ARG_UNUSED(dev); + + if (!IN_RANGE(pclken->bus, STM32_CLOCK_PERIPH_MIN, STM32_CLOCK_PERIPH_MAX)) { + /* Attempt to change a wrong periph clock bit */ + return -ENOTSUP; + } + + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, pclken->enr); + + return 0; +} + +static int stm32_clock_control_off(const struct device *dev, clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *) sub_system; + + ARG_UNUSED(dev); + + if (!IN_RANGE(pclken->bus, STM32_CLOCK_PERIPH_MIN, STM32_CLOCK_PERIPH_MAX)) { + /* Attempt to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, pclken->enr); + + return 0; +} + +static int stm32_clock_control_get_subsys_rate(const struct device *dev, + clock_control_subsys_t sub_system, uint32_t *rate) +{ + ARG_UNUSED(dev); + ARG_UNUSED(sub_system); + ARG_UNUSED(rate); + return -ENOTSUP; +} + +static DEVICE_API(clock_control, stm32_clock_control_api) = { + .on = stm32_clock_control_on, + .off = stm32_clock_control_off, + .get_rate = stm32_clock_control_get_subsys_rate, +}; + +static int stm32_clock_control_init(const struct device *dev) +{ + ARG_UNUSED(dev); + return 0; +} + +/** + * @brief RCC device, note that priority is intentionally set to 1 so + * that the device init runs just after SOC init + */ +DEVICE_DT_DEFINE(DT_NODELABEL(rcc), stm32_clock_control_init, NULL, NULL, NULL, PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &stm32_clock_control_api); diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index e654ac2860ea..8f242f4af828 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -41,6 +41,8 @@ #elif defined(CONFIG_SOC_SERIES_STM32L4X) || \ defined(CONFIG_SOC_SERIES_STM32L5X) #include +#elif defined(CONFIG_SOC_SERIES_STM32MP2X) +#include #elif defined(CONFIG_SOC_SERIES_STM32WBX) #include #elif defined(CONFIG_SOC_SERIES_STM32WB0X) From 4583a3e8a0f69406f46a6cfb7bc114dddb41512c Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Tue, 22 Apr 2025 13:35:45 +0200 Subject: [PATCH 11/13] drivers: gpio: add mp2 gpio clock handling Remove gpio clock management from the GPIO driver when running on the cortex-m33 on the mp2 and gpio clocks are managed by the cortex-A, being the resource manager, allowed by the Resource Isolation Framework (RIF). Also add a specific binding for the mp2 gpio to make clock property optional. Signed-off-by: Youssef Zini --- drivers/gpio/Kconfig.stm32 | 3 ++- drivers/gpio/gpio_stm32.c | 11 ++++++++--- dts/bindings/gpio/st,stm32mp2-gpio.yaml | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 dts/bindings/gpio/st,stm32mp2-gpio.yaml diff --git a/drivers/gpio/Kconfig.stm32 b/drivers/gpio/Kconfig.stm32 index d414cfae4e5f..d05baf9c4ce1 100644 --- a/drivers/gpio/Kconfig.stm32 +++ b/drivers/gpio/Kconfig.stm32 @@ -1,11 +1,12 @@ # STM32 GPIO configuration # Copyright (c) 2016 Open-RnD Sp. z o.o. +# Copyright (C) 2025 Savoir-faire Linux, Inc. # SPDX-License-Identifier: Apache-2.0 config GPIO_STM32 bool "GPIO Driver for STM32 family of MCUs" default y - depends on DT_HAS_ST_STM32_GPIO_ENABLED + depends on DT_HAS_ST_STM32_GPIO_ENABLED || DT_HAS_ST_STM32MP2_GPIO_ENABLED help Enable GPIO driver for STM32 line of MCUs diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index b5fa7aeec943..3da32fdc7216 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Open-RnD Sp. z o.o. + * Copyright (C) 2025 Savoir-faire Linux, Inc. * * SPDX-License-Identifier: Apache-2.0 */ @@ -708,7 +709,7 @@ static int gpio_stm32_pm_action(const struct device *dev, * * @return 0 */ -static int gpio_stm32_init(const struct device *dev) +__maybe_unused static int gpio_stm32_init(const struct device *dev) { struct gpio_stm32_data *data = dev->data; @@ -737,12 +738,16 @@ static int gpio_stm32_init(const struct device *dev) }, \ .base = (uint32_t *)__base_addr, \ .port = __port, \ - .pclken = { .bus = __bus, .enr = __cenr } \ + COND_CODE_1(DT_NODE_HAS_PROP(__node, clocks), \ + (.pclken = { .bus = __bus, .enr = __cenr },), \ + (/* Nothing if clocks not present */)) \ }; \ static struct gpio_stm32_data gpio_stm32_data_## __suffix; \ PM_DEVICE_DT_DEFINE(__node, gpio_stm32_pm_action); \ DEVICE_DT_DEFINE(__node, \ - gpio_stm32_init, \ + COND_CODE_1(DT_NODE_HAS_PROP(__node, clocks), \ + (gpio_stm32_init), \ + (NULL)), \ PM_DEVICE_DT_GET(__node), \ &gpio_stm32_data_## __suffix, \ &gpio_stm32_cfg_## __suffix, \ diff --git a/dts/bindings/gpio/st,stm32mp2-gpio.yaml b/dts/bindings/gpio/st,stm32mp2-gpio.yaml new file mode 100644 index 000000000000..09b20ce063fb --- /dev/null +++ b/dts/bindings/gpio/st,stm32mp2-gpio.yaml @@ -0,0 +1,23 @@ +# Copyright (C) 2025 Savoir-faire Linux, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: STM32MP2 GPIO Controller + +compatible: "st,stm32mp2-gpio" + +include: + - name: st,stm32-gpio.yaml + property-blocklist: + - clocks + +properties: + clocks: + type: phandle-array + description: | + The clocks property is optional for STM32MP2 GPIO controllers. + This property is not required when the Cortex-A core is responsible for + GPIO initialization and acts as the resource manager, as defined by the + RIF (Resource Isolation Framework) peripheral. Adding the GPIO clocks + in that case would only trigger an IAC event. + If the Cortex-M core is designated as the resource manager, then the + clocks property must be defined and added to the device tree. From 316b93becf8d0f7deba3049c612ea81cd05bb81d Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Mon, 19 May 2025 17:42:41 +0200 Subject: [PATCH 12/13] dts: arm: st: stm32mp2_m33.dtsi: add GPIO nodes Add GPIO A-K nodes to the device tree for STM32MP2 SoC. Note that GPIOs are disabled by default in the STM32MP2 SoC. Signed-off-by: Youssef Zini --- dts/arm/st/mp2/stm32mp2_m33.dtsi | 97 ++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/dts/arm/st/mp2/stm32mp2_m33.dtsi b/dts/arm/st/mp2/stm32mp2_m33.dtsi index 3c53fd6676b6..9da9e1f12573 100644 --- a/dts/arm/st/mp2/stm32mp2_m33.dtsi +++ b/dts/arm/st/mp2/stm32mp2_m33.dtsi @@ -7,6 +7,8 @@ #include #include #include +#include +#include / { cpus { @@ -56,6 +58,101 @@ <8 1>, <9 1>, <10 1>, <11 1>, <12 1>, <13 1>, <14 1>, <15 1>; }; + + pinctrl: pin-controller@44240000 { + compatible = "st,stm32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x44240000 0xb0000>; + + gpioa: gpio@44240000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x44240000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpiob: gpio@44250000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x44250000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpioc: gpio@44260000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x44260000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpiod: gpio@44270000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x44270000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpioe: gpio@44280000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x44280000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpiof: gpio@44290000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x44290000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpiog: gpio@442a0000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x442a0000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpioh: gpio@442b0000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x442b0000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpioi: gpio@442c0000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x442c0000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpioj: gpio@442d0000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x442d0000 DT_SIZE_K(1)>; + status = "disabled"; + }; + + gpiok: gpio@442e0000 { + compatible = "st,stm32mp2-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x442e0000 DT_SIZE_K(1)>; + status = "disabled"; + }; + }; }; }; From d7785b146494b558e4bf92c7ed552005dcd446de Mon Sep 17 00:00:00 2001 From: Youssef Zini Date: Mon, 19 May 2025 17:18:46 +0200 Subject: [PATCH 13/13] boards: add gpio, button and led support Add gpio support for STM32MP257F-EV1 board. Add the orange (&led0) LED to the device tree and enable GPIOJ. Add the user button USER2 to the device tree and enable GPIOG. This step allows building and debugging the blinky and button sample applications. Signed-off-by: Youssef Zini --- .../stm32mp257f_ev1_stm32mp257fxx_m33.dts | 34 +++++++++++++++++++ ...tm32mp257f_ev1_stm32mp257fxx_m33_defconfig | 3 ++ 2 files changed, 37 insertions(+) diff --git a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.dts b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.dts index 35225a95a92f..61f83448a953 100644 --- a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.dts +++ b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33.dts @@ -6,6 +6,8 @@ /dts-v1/; #include +#include +#include / { model = "STMicroelectronics STM32MP257F-EV1 board"; @@ -15,8 +17,40 @@ zephyr,flash = &ddr_code; zephyr,sram = &ddr_sys; }; + + leds { + compatible = "gpio-leds"; + + orange_led_3: led_3 { + gpios = <&gpioj 6 GPIO_ACTIVE_HIGH>; + label = "LD3"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + button_user2: button2 { + label = "User 2"; + gpios = <&gpiog 8 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &orange_led_3; + sw0 = &button_user2; + }; }; &rcc { clock-frequency = ; }; + +&gpiog { + status = "okay"; +}; + +&gpioj { + status = "okay"; +}; diff --git a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig index 0fdf892fff35..ba770561fbe1 100644 --- a/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig +++ b/boards/st/stm32mp257f_ev1/stm32mp257f_ev1_stm32mp257fxx_m33_defconfig @@ -4,5 +4,8 @@ # Enable MPU CONFIG_ARM_MPU=y +# Enable GPIO +CONFIG_GPIO=y + # Enable HW stack protection CONFIG_HW_STACK_PROTECTION=y