From 7890ef62dcab110f117c16ec3bd7af43aca289f9 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:31:48 +0100 Subject: [PATCH 01/15] west.yml: update west.yml for stm32n6 hal Update west.yml for STM32N6 HAL Signed-off-by: Guillaume Gautier --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index eb8ac3785d30f..49a4eb111c1c4 100644 --- a/west.yml +++ b/west.yml @@ -238,7 +238,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: 37842371f5ef0078ad32f16e5059c1df58b51892 + revision: 1d1f81866ccbaa6e84e9960ed763e005d1e45560 path: modules/hal/stm32 groups: - hal From 0b663e41c4311e56647b54b4292bdd1254330852 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Wed, 22 Jan 2025 14:13:44 +0100 Subject: [PATCH 02/15] modules: stm32: add stm32n6 cube modules Add STM32N6 Cube HAL and LL modules Signed-off-by: Guillaume Gautier --- modules/Kconfig.stm32 | 47 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/Kconfig.stm32 b/modules/Kconfig.stm32 index c586a51fcf752..c7d4437fd1316 100644 --- a/modules/Kconfig.stm32 +++ b/modules/Kconfig.stm32 @@ -30,6 +30,16 @@ config USE_STM32_HAL_ADC_EX Enable STM32Cube Extended Analog-to-Digital Converter (ADC) HAL module driver +config USE_STM32_HAL_BSEC + bool + help + Enable STM32Cube Boot and Security Control (BSEC) HAL module driver + +config USE_STM32_HAL_CACHEAXI + bool + help + Enable STM32Cube AXI Cache (CACHEAXI) HAL module driver + config USE_STM32_HAL_CAN bool help @@ -213,6 +223,11 @@ config USE_STM32_HAL_GFXMMU help Enable STM32Cube Chrom-GRCTM (GFXMMU) HAL module driver +config USE_STM32_HAL_GFXTIM + bool + help + Enable STM32Cube Graphic Timer (GFXTIM) HAL module driver + config USE_STM32_HAL_GPIO bool help @@ -335,6 +350,11 @@ config USE_STM32_HAL_LTDC_EX help Enable STM32Cube Extended LCD-TFT controller (LTDC) HAL module driver +config USE_STM32_HAL_MCE + bool + help + Enable STM32Cube Memory Cipher Engine (MCE) HAL module driver + config USE_STM32_HAL_MDF bool help @@ -463,11 +483,21 @@ config USE_STM32_HAL_RAMECC help Enable STM32Cube RAM ECC monitoring (RAMECC) HAL module driver +config USE_STM32_HAL_RIF + bool + help + Enable STM32Cube Resource Isolation Framework (RIF) HAL module driver + config USE_STM32_HAL_RNG bool help Enable STM32Cube True random number generator (RNG) HAL module driver +config USE_STM32_HAL_RNG_EX + bool + help + Enable STM32Cube Extended True random number generator (RNG) HAL module driver + config USE_STM32_HAL_RTC bool help @@ -533,6 +563,11 @@ config USE_STM32_HAL_SMBUS help Enable STM32Cube System Management Bus (SMBus) HAL module driver +config USE_STM32_HAL_SMBUS_EX + bool + help + Enable STM32Cube Extended System Management Bus (SMBus) HAL module driver + config USE_STM32_HAL_SPDIFRX bool help @@ -656,7 +691,7 @@ config USE_STM32_LL_DELAYBLOCK config USE_STM32_LL_DLYB bool help - Enable STM32Cube DelayBlock (DELAYBLOCK) LL module driver (stm32U5) + Enable STM32Cube DelayBlock (DELAYBLOCK) LL module driver (stm32U5 or STM32N6) config USE_STM32_LL_DMA bool @@ -823,4 +858,14 @@ config USE_STM32_LL_UTILS help Enable STM32Cube Utility functions (UTILS) LL module driver +config USE_STM32_LL_VENC + bool + help + Enable STM32Cube Video Encoder (VENC) LL module driver + +config USE_STM32_UTIL_I3C + bool + help + Enable STM32Cube I3C Timing Utility functions (UTILS) module driver + endif # HAS_STM32CUBE From 7e1459882276757e7993e24c6dd33957bb5050fc Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:15:40 +0100 Subject: [PATCH 03/15] soc: st: stm32: add stm32n6 series Add STM32N6 series Signed-off-by: Guillaume Gautier --- soc/st/stm32/soc.yml | 3 + soc/st/stm32/stm32n6x/CMakeLists.txt | 10 +++ soc/st/stm32/stm32n6x/Kconfig | 18 ++++++ soc/st/stm32/stm32n6x/Kconfig.defconfig | 17 +++++ .../stm32n6x/Kconfig.defconfig.stm32n657xx | 11 ++++ soc/st/stm32/stm32n6x/Kconfig.soc | 18 ++++++ soc/st/stm32/stm32n6x/soc.c | 62 +++++++++++++++++++ soc/st/stm32/stm32n6x/soc.h | 22 +++++++ 8 files changed, 161 insertions(+) create mode 100644 soc/st/stm32/stm32n6x/CMakeLists.txt create mode 100644 soc/st/stm32/stm32n6x/Kconfig create mode 100644 soc/st/stm32/stm32n6x/Kconfig.defconfig create mode 100644 soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx create mode 100644 soc/st/stm32/stm32n6x/Kconfig.soc create mode 100644 soc/st/stm32/stm32n6x/soc.c create mode 100644 soc/st/stm32/stm32n6x/soc.h diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index ba24bcf143ec6..4e5d659573395 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -186,6 +186,9 @@ family: - name: stm32mp1x socs: - name: stm32mp157cxx + - name: stm32n6x + socs: + - name: stm32n657xx - name: stm32u0x socs: - name: stm32u031xx diff --git a/soc/st/stm32/stm32n6x/CMakeLists.txt b/soc/st/stm32/stm32n6x/CMakeLists.txt new file mode 100644 index 0000000000000..eebd281cd96be --- /dev/null +++ b/soc/st/stm32/stm32n6x/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_sources( + soc.c + ) + +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/st/stm32/stm32n6x/Kconfig b/soc/st/stm32/stm32n6x/Kconfig new file mode 100644 index 0000000000000..853261ac18332 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig @@ -0,0 +1,18 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32N6X + select ARM + select CPU_CORTEX_M55 + select ARM_TRUSTZONE_M + select CPU_HAS_ARM_SAU + select CPU_HAS_ARM_MPU + select CPU_HAS_FPU + select ARMV8_M_DSP + select CPU_CORTEX_M_HAS_DWT + select HAS_STM32CUBE + select INIT_ARCH_HW_AT_BOOT + select SOC_RESET_HOOK + select TRUSTED_EXECUTION_SECURE diff --git a/soc/st/stm32/stm32n6x/Kconfig.defconfig b/soc/st/stm32/stm32n6x/Kconfig.defconfig new file mode 100644 index 0000000000000..2e9856e8b02a2 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig.defconfig @@ -0,0 +1,17 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_STM32N6X + +rsource "Kconfig.defconfig.stm32n6*" + +DT_STM32_CPU_CLOCK_PATH := $(dt_nodelabel_path,cpusw) +DT_STM32_CPU_CLOCK_FREQ := $(dt_node_int_prop_int,$(DT_STM32_CPU_CLOCK_PATH),clock-frequency) + +# For STM32N6, override the value defined in STM32 Kconfig to use CPU clock frequency +config SYS_CLOCK_HW_CYCLES_PER_SEC + default "$(DT_STM32_CPU_CLOCK_FREQ)" if "$(dt_nodelabel_enabled,cpusw)" + +endif # SOC_SERIES_STM32N6X diff --git a/soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx b/soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx new file mode 100644 index 0000000000000..910e642669077 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx @@ -0,0 +1,11 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32N657XX + +config NUM_IRQS + default 194 + +endif # SOC_STM32N657XX diff --git a/soc/st/stm32/stm32n6x/Kconfig.soc b/soc/st/stm32/stm32n6x/Kconfig.soc new file mode 100644 index 0000000000000..71879c0848a38 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig.soc @@ -0,0 +1,18 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32N6X + bool + select SOC_FAMILY_STM32 + +config SOC_SERIES + default "stm32n6x" if SOC_SERIES_STM32N6X + +config SOC_STM32N657XX + bool + select SOC_SERIES_STM32N6X + +config SOC + default "stm32n657xx" if SOC_STM32N657XX diff --git a/soc/st/stm32/stm32n6x/soc.c b/soc/st/stm32/stm32n6x/soc.c new file mode 100644 index 0000000000000..c967404862c17 --- /dev/null +++ b/soc/st/stm32/stm32n6x/soc.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief System/hardware module for STM32N6 processor + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +LOG_MODULE_REGISTER(soc); + +extern char _vector_start[]; +void *g_pfnVectors = (void *)_vector_start; + +#if defined(CONFIG_SOC_RESET_HOOK) +void soc_reset_hook(void) +{ + /* This is provided by STM32Cube HAL */ + SystemInit(); +} +#endif + +/** + * @brief Perform basic hardware initialization at boot. + * + * This needs to be run from the very beginning. + * + * @return 0 + */ +void soc_early_init_hook(void) +{ + /* Enable caches */ + sys_cache_instr_enable(); + sys_cache_data_enable(); + + /* Update CMSIS SystemCoreClock variable (HCLK) */ + /* At reset, system core clock is set to 64 MHz from HSI */ + SystemCoreClock = 64000000; + + /* Enable PWR */ + LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR); + + /* Enable IOs */ + LL_PWR_EnableVddIO2(); + LL_PWR_EnableVddIO3(); + LL_PWR_EnableVddIO4(); + LL_PWR_EnableVddIO5(); +} diff --git a/soc/st/stm32/stm32n6x/soc.h b/soc/st/stm32/stm32n6x/soc.h new file mode 100644 index 0000000000000..9274a7db70b71 --- /dev/null +++ b/soc/st/stm32/stm32n6x/soc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the STM32N6 family processors. + * + */ + + +#ifndef _STM32N6_SOC_H_ +#define _STM32N6_SOC_H_ + +#ifndef _ASMLANGUAGE + +#include + +#endif /* !_ASMLANGUAGE */ + +#endif /* _STM32N6_SOC_H_ */ From 90dc9affe112239098e0f8a69968c4698fb76e47 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Mon, 27 Jan 2025 12:22:08 +0100 Subject: [PATCH 04/15] soc: st: stm32: add a comment for kconfig source priority Add a comment describing Kconfig source order priority to prevent future questions (after overriding SYS_CLOCK_HW_CYCLES_PER_SEC config for STM32N6). Signed-off-by: Guillaume Gautier --- soc/st/stm32/Kconfig.defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soc/st/stm32/Kconfig.defconfig b/soc/st/stm32/Kconfig.defconfig index 0741439de6c79..67879e6cf6285 100644 --- a/soc/st/stm32/Kconfig.defconfig +++ b/soc/st/stm32/Kconfig.defconfig @@ -7,6 +7,8 @@ if SOC_FAMILY_STM32 +# Source series Kconfig files first, so SoCs +# can override the defaults given here rsource "*/Kconfig.defconfig" config CLOCK_CONTROL From 3767d91f8fdc94da949a79ade4f14454282b4382 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:17:45 +0100 Subject: [PATCH 05/15] dts: bindings: clock: add stm32n6 rcc clocks Add STM32N6 RCC clock bindings Signed-off-by: Guillaume Gautier --- .../clock/st,stm32n6-cpu-clock-mux.yaml | 29 ++++ dts/bindings/clock/st,stm32n6-hse-clock.yaml | 21 +++ .../clock/st,stm32n6-ic-clock-mux.yaml | 33 +++++ dts/bindings/clock/st,stm32n6-pll-clock.yaml | 62 +++++++++ dts/bindings/clock/st,stm32n6-rcc.yaml | 125 ++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100644 dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml create mode 100644 dts/bindings/clock/st,stm32n6-hse-clock.yaml create mode 100644 dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml create mode 100644 dts/bindings/clock/st,stm32n6-pll-clock.yaml create mode 100644 dts/bindings/clock/st,stm32n6-rcc.yaml diff --git a/dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml b/dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml new file mode 100644 index 0000000000000..653a0b0a15a5b --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2025, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32N6 CPU Clock + Describes the STM32N6 CPU clock multiplexer. On STM32N6, this is the CPU + clock that feeds the SysTick. + For instance: + &cpusw { + clocks = <&rcc STM32_SRC_IC1 CPU_SEL(3)>; + clock-frequency = ; + status = "okay"; + }; + +compatible: "st,stm32n6-cpu-clock-mux" + +include: + - name: base.yaml + property-allowlist: + - status + - compatible + - clocks + +properties: + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for CPU clock (sysa_ck/sys_cpu_ck) diff --git a/dts/bindings/clock/st,stm32n6-hse-clock.yaml b/dts/bindings/clock/st,stm32n6-hse-clock.yaml new file mode 100644 index 0000000000000..36234050230f7 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-hse-clock.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STM32N6 HSE Clock + +compatible: "st,stm32n6-hse-clock" + +include: [fixed-clock.yaml] + +properties: + hse-bypass: + type: boolean + description: | + HSE crystal oscillator bypass + Set to the property to by-pass the oscillator with an external clock. + + hse-div2: + type: boolean + description: | + When set HSE output clock is divided by 2. + Otherwise, no prescaler is used. diff --git a/dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml b/dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml new file mode 100644 index 0000000000000..2462d3166b751 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml @@ -0,0 +1,33 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32N6 Divider IC multiplexer + This node select a clock input and a divider. + For instance: + &ic6 { + pll-src = <2>; + div = <16>; + status = "okay"; + }; + +compatible: "st,stm32n6-ic-clock-mux" + +properties: + pll-src: + type: int + required: true + description: | + PLL clock source + enum: + - 1 + - 2 + - 3 + - 4 + + ic-div: + type: int + description: | + ICx integer division factor + The input ICx frequency is divided by the specified value + Valid range: 1 - 256 diff --git a/dts/bindings/clock/st,stm32n6-pll-clock.yaml b/dts/bindings/clock/st,stm32n6-pll-clock.yaml new file mode 100644 index 0000000000000..b445304aa7d79 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-pll-clock.yaml @@ -0,0 +1,62 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + PLL node binding for STM32N6 devices + + It can be used to describe 4 different PLLs: PLL1, PLL2, PLL3 and PLL4. + + These PLLs can take one of clk_hse, clk_hsi or clk_msi as input clock, with + an input frequency from 5 to 50 MHz. PLLM factor is used to set the input + clock in this acceptable range. + + Each PLL has one output clock whose frequency can be computed with the + following formula: + + f(PLL_P) = f(VCO clock) / (PLLP1 × PLLP2) + + with f(VCO clock) = f(PLL clock input) × (PLLN / PLLM) + + Note: To reduce the power consumption, it is recommended to configure the VCOx + clock output to the lowest frequency. + + The PLL output frequency must not exceed 3200 MHz. + +compatible: "st,stm32n6-pll-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + + "#clock-cells": + const: 0 + + clocks: + required: true + + div-m: + type: int + required: true + description: | + Prescaler for PLLx + input clock + Valid range: 1 - 63 + + mul-n: + type: int + required: true + description: | + PLLx multiplication factor for VCO + Valid range: 16 - 2500 + + div-p1: + type: int + description: | + PLLx DIVP1 division factor + Valid range: 1 - 7 + + div-p2: + type: int + description: | + PLLx DIVP2 division factor + Valid range: 1 - 7 diff --git a/dts/bindings/clock/st,stm32n6-rcc.yaml b/dts/bindings/clock/st,stm32n6-rcc.yaml new file mode 100644 index 0000000000000..b3e1750e42a83 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-rcc.yaml @@ -0,0 +1,125 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 Reset and Clock controller node for STM32N6 devices + This node is in charge of system clock ('SYSCLK') source selection and + System Clock Generation. + + Configuring STM32 Reset and Clock controller node: + + System clock source should be selected amongst the clock nodes available in "clocks" + node (typically 'clk_hse, clk_csi', 'pll', ...). + As part of this node configuration, SYSCLK frequency should also be defined, using + "clock-frequency" property. + Last, bus clocks (typically HCLK, PCLK1, PCLK2) should be configured using matching + prescaler properties. + Here is an example of correctly configured rcc node: + &rcc { + clocks = <&ic2>; + clock-frequency = ; + ahb-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb4-prescaler = <1>; + apb5-prescaler = <1>; + } + + Confere st,stm32-rcc binding for information about domain clocks configuration. + +compatible: "st,stm32n6-rcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for clock output + + ahb-prescaler: + type: int + required: true + description: | + AHB clock prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb1-prescaler: + type: int + required: true + description: | + CPU domain APB1 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb2-prescaler: + type: int + required: true + description: | + CPU domain APB2 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb4-prescaler: + type: int + required: true + description: | + CPU domain APB4 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb5-prescaler: + type: int + required: true + description: | + CPU domain APB5 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + +clock-cells: + - bus + - bits From 7d698c4f14e2c092b522e03d42f49ab566e54977 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:18:31 +0100 Subject: [PATCH 06/15] drivers: clock: add stm32n6 clock Add STM32N6 clock driver. Supported clocks are LSE, LSI, HSE, HSI, PLL1-4, IC1-20, peripheral clock and CPU clock. Signed-off-by: Guillaume Gautier --- drivers/clock_control/CMakeLists.txt | 2 + drivers/clock_control/Kconfig.stm32 | 3 +- drivers/clock_control/clock_stm32_ll_n6.c | 950 ++++++++++++++++++ .../clock_control/stm32_clock_control.h | 189 ++++ .../zephyr/dt-bindings/clock/stm32_clock.h | 1 + .../zephyr/dt-bindings/clock/stm32n6_clock.h | 193 ++++ 6 files changed, 1337 insertions(+), 1 deletion(-) create mode 100644 drivers/clock_control/clock_stm32_ll_n6.c create mode 100644 include/zephyr/dt-bindings/clock/stm32n6_clock.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 8c451149a584f..9d7a87e03e671 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -59,6 +59,8 @@ elseif(CONFIG_SOC_SERIES_STM32H7RSX) zephyr_library_sources(clock_stm32_ll_h7.c) elseif(CONFIG_SOC_SERIES_STM32H5X) zephyr_library_sources(clock_stm32_ll_h5.c) +elseif(CONFIG_SOC_SERIES_STM32N6X) + zephyr_library_sources(clock_stm32_ll_n6.c) elseif(CONFIG_SOC_SERIES_STM32U5X) zephyr_library_sources(clock_stm32_ll_u5.c) elseif(CONFIG_SOC_SERIES_STM32WB0X) diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 47a1b790a7b0d..d99fa3b62eb29 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -10,7 +10,8 @@ menuconfig CLOCK_CONTROL_STM32_CUBE default y select USE_STM32_LL_UTILS select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \ - SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) + SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32N6X) select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ $(dt_nodelabel_has_prop,clk_hse,css-enabled)) help diff --git a/drivers/clock_control/clock_stm32_ll_n6.c b/drivers/clock_control/clock_stm32_ll_n6.c new file mode 100644 index 0000000000000..e69faf6823d5b --- /dev/null +++ b/drivers/clock_control/clock_stm32_ll_n6.c @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Macros to fill up prescaler values */ +#define z_ic_src_pll(v) LL_RCC_ICCLKSOURCE_PLL ## v +#define ic_src_pll(v) z_ic_src_pll(v) + +#define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v +#define hsi_divider(v) z_hsi_divider(v) + +#define z_ahb_prescaler(v) LL_RCC_AHB_DIV_ ## v +#define ahb_prescaler(v) z_ahb_prescaler(v) + +#define z_apb1_prescaler(v) LL_RCC_APB1_DIV_ ## v +#define apb1_prescaler(v) z_apb1_prescaler(v) + +#define z_apb2_prescaler(v) LL_RCC_APB2_DIV_ ## v +#define apb2_prescaler(v) z_apb2_prescaler(v) + +#define z_apb4_prescaler(v) LL_RCC_APB4_DIV_ ## v +#define apb4_prescaler(v) z_apb4_prescaler(v) + +#define z_apb5_prescaler(v) LL_RCC_APB5_DIV_ ## v +#define apb5_prescaler(v) z_apb5_prescaler(v) + +#define PLL1_ID 1 +#define PLL2_ID 2 +#define PLL3_ID 3 +#define PLL4_ID 4 + + +static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) +{ + return clock / prescaler; +} + +__unused +/** @brief returns the pll source frequency of given pll_id */ +static uint32_t get_pllsrc_frequency(int pll_id) +{ + if ((IS_ENABLED(STM32_PLL_SRC_HSI) && pll_id == PLL1_ID) || + (IS_ENABLED(STM32_PLL2_SRC_HSI) && pll_id == PLL2_ID) || + (IS_ENABLED(STM32_PLL3_SRC_HSI) && pll_id == PLL3_ID) || + (IS_ENABLED(STM32_PLL4_SRC_HSI) && pll_id == PLL4_ID)) { + return STM32_HSI_FREQ; + } else if ((IS_ENABLED(STM32_PLL_SRC_HSE) && pll_id == PLL1_ID) || + (IS_ENABLED(STM32_PLL2_SRC_HSE) && pll_id == PLL2_ID) || + (IS_ENABLED(STM32_PLL3_SRC_HSE) && pll_id == PLL3_ID) || + (IS_ENABLED(STM32_PLL4_SRC_HSE) && pll_id == PLL4_ID)) { + return STM32_HSE_FREQ; + } + + __ASSERT(0, "No PLL Source configured"); + return 0; +} + +static uint32_t get_pllout_frequency(int pll_id) +{ + uint32_t pllsrc_freq = get_pllsrc_frequency(pll_id); + int pllm_div; + int plln_mul; + int pllout_div1; + int pllout_div2; + + switch (pll_id) { +#if defined(STM32_PLL1_ENABLED) + case PLL1_ID: + pllm_div = STM32_PLL1_M_DIVISOR; + plln_mul = STM32_PLL1_N_MULTIPLIER; + pllout_div1 = STM32_PLL1_P1_DIVISOR; + pllout_div2 = STM32_PLL1_P2_DIVISOR; + break; +#endif /* STM32_PLL1_ENABLED */ +#if defined(STM32_PLL2_ENABLED) + case PLL2_ID: + pllm_div = STM32_PLL2_M_DIVISOR; + plln_mul = STM32_PLL2_N_MULTIPLIER; + pllout_div1 = STM32_PLL2_P1_DIVISOR; + pllout_div2 = STM32_PLL2_P2_DIVISOR; + break; +#endif /* STM32_PLL2_ENABLED */ +#if defined(STM32_PLL3_ENABLED) + case PLL3_ID: + pllm_div = STM32_PLL3_M_DIVISOR; + plln_mul = STM32_PLL3_N_MULTIPLIER; + pllout_div1 = STM32_PLL3_P1_DIVISOR; + pllout_div2 = STM32_PLL3_P2_DIVISOR; + break; +#endif /* STM32_PLL3_ENABLED */ +#if defined(STM32_PLL4_ENABLED) + case PLL4_ID: + pllm_div = STM32_PLL4_M_DIVISOR; + plln_mul = STM32_PLL4_N_MULTIPLIER; + pllout_div1 = STM32_PLL4_P1_DIVISOR; + pllout_div2 = STM32_PLL4_P2_DIVISOR; + break; +#endif /* STM32_PLL4_ENABLED */ + default: + __ASSERT(0, "No PLL configured"); + return 0; + } + + __ASSERT_NO_MSG(pllm_div && pllout_div1 && pllout_div2); + + return (pllsrc_freq / pllm_div) * plln_mul / (pllout_div1 * pllout_div2); +} + +__unused uint32_t get_icout_frequency(uint32_t icsrc, int div) +{ + if (icsrc == LL_RCC_ICCLKSOURCE_PLL1) { + return get_pllout_frequency(PLL1_ID) / div; + } else if (icsrc == LL_RCC_ICCLKSOURCE_PLL2) { + return get_pllout_frequency(PLL2_ID) / div; + } else if (icsrc == LL_RCC_ICCLKSOURCE_PLL3) { + return get_pllout_frequency(PLL3_ID) / div; + } else if (icsrc == LL_RCC_ICCLKSOURCE_PLL4) { + return get_pllout_frequency(PLL4_ID) / div; + } + + __ASSERT(0, "No IC Source configured"); + return 0; +} + +static uint32_t get_sysclk_frequency(void) +{ +#if defined(STM32_SYSCLK_SRC_HSE) + return STM32_HSE_FREQ; +#elif defined(STM32_SYSCLK_SRC_HSI) + return STM32_HSI_FREQ; +#elif defined(STM32_SYSCLK_SRC_IC2) + return get_icout_frequency(LL_RCC_IC2_GetSource(), STM32_IC2_DIV); +#else + __ASSERT(0, "No SYSCLK Source configured"); + return 0; +#endif + +} + + +/** @brief Verifies clock is part of active clock configuration */ +static int enabled_clock(uint32_t src_clk) +{ + if ((src_clk == STM32_SRC_SYSCLK) || + ((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) || + ((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) || + ((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) || + ((src_clk == STM32_SRC_HSI) && IS_ENABLED(STM32_HSI_ENABLED)) || + ((src_clk == STM32_SRC_PLL1) && IS_ENABLED(STM32_PLL1_ENABLED)) || + ((src_clk == STM32_SRC_PLL2) && IS_ENABLED(STM32_PLL2_ENABLED)) || + ((src_clk == STM32_SRC_PLL3) && IS_ENABLED(STM32_PLL3_ENABLED)) || + ((src_clk == STM32_SRC_PLL4) && IS_ENABLED(STM32_PLL4_ENABLED)) || + ((src_clk == STM32_SRC_CKPER) && IS_ENABLED(STM32_CKPER_ENABLED)) || + ((src_clk == STM32_SRC_IC1) && IS_ENABLED(STM32_IC1_ENABLED)) || + ((src_clk == STM32_SRC_IC2) && IS_ENABLED(STM32_IC2_ENABLED)) || + ((src_clk == STM32_SRC_IC3) && IS_ENABLED(STM32_IC3_ENABLED)) || + ((src_clk == STM32_SRC_IC4) && IS_ENABLED(STM32_IC4_ENABLED)) || + ((src_clk == STM32_SRC_IC5) && IS_ENABLED(STM32_IC5_ENABLED)) || + ((src_clk == STM32_SRC_IC6) && IS_ENABLED(STM32_IC6_ENABLED)) || + ((src_clk == STM32_SRC_IC7) && IS_ENABLED(STM32_IC7_ENABLED)) || + ((src_clk == STM32_SRC_IC8) && IS_ENABLED(STM32_IC8_ENABLED)) || + ((src_clk == STM32_SRC_IC9) && IS_ENABLED(STM32_IC9_ENABLED)) || + ((src_clk == STM32_SRC_IC10) && IS_ENABLED(STM32_IC10_ENABLED)) || + ((src_clk == STM32_SRC_IC11) && IS_ENABLED(STM32_IC11_ENABLED)) || + ((src_clk == STM32_SRC_IC12) && IS_ENABLED(STM32_IC12_ENABLED)) || + ((src_clk == STM32_SRC_IC13) && IS_ENABLED(STM32_IC13_ENABLED)) || + ((src_clk == STM32_SRC_IC14) && IS_ENABLED(STM32_IC14_ENABLED)) || + ((src_clk == STM32_SRC_IC15) && IS_ENABLED(STM32_IC15_ENABLED)) || + ((src_clk == STM32_SRC_IC16) && IS_ENABLED(STM32_IC16_ENABLED)) || + ((src_clk == STM32_SRC_IC17) && IS_ENABLED(STM32_IC17_ENABLED)) || + ((src_clk == STM32_SRC_IC18) && IS_ENABLED(STM32_IC18_ENABLED)) || + ((src_clk == STM32_SRC_IC19) && IS_ENABLED(STM32_IC19_ENABLED)) || + ((src_clk == STM32_SRC_IC20) && IS_ENABLED(STM32_IC20_ENABLED))) { + return 0; + } + + return -ENOTSUP; +} + +static inline 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_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attempt to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + /* Set Run clock */ + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, + pclken->enr); + + /* Set Low Power clock */ + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus + STM32_CLOCK_LP_BUS_SHIFT, + pclken->enr); + + return 0; +} + +static inline 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_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attempt to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + /* Clear Run clock */ + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, + pclken->enr); + + /* Clear Low Power clock */ + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus + STM32_CLOCK_LP_BUS_SHIFT, + pclken->enr); + + return 0; +} + +static inline int stm32_clock_control_configure(const struct device *dev, + clock_control_subsys_t sub_system, + void *data) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + int err; + + ARG_UNUSED(dev); + ARG_UNUSED(data); + + err = enabled_clock(pclken->bus); + if (err < 0) { + /* Attempt to configure a src clock not available or not valid */ + return err; + } + + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_CLOCK_REG_GET(pclken->enr), + STM32_CLOCK_MASK_GET(pclken->enr) << STM32_CLOCK_SHIFT_GET(pclken->enr)); + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_CLOCK_REG_GET(pclken->enr), + STM32_CLOCK_VAL_GET(pclken->enr) << STM32_CLOCK_SHIFT_GET(pclken->enr)); + + return 0; +} + +static int stm32_clock_control_get_subsys_rate(const struct device *dev, + clock_control_subsys_t sys, + uint32_t *rate) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sys); + + uint32_t sys_clock = get_sysclk_frequency(); + uint32_t ahb_clock = get_bus_clock(sys_clock, STM32_AHB_PRESCALER); + + ARG_UNUSED(dev); + + switch (pclken->bus) { + case STM32_SRC_SYSCLK: + *rate = get_sysclk_frequency(); + break; + case STM32_CLOCK_BUS_AHB1: + case STM32_CLOCK_BUS_AHB2: + case STM32_CLOCK_BUS_AHB3: + case STM32_CLOCK_BUS_AHB4: + case STM32_CLOCK_BUS_AHB5: + *rate = ahb_clock; + break; + case STM32_CLOCK_BUS_APB1: + case STM32_CLOCK_BUS_APB1_2: + *rate = get_bus_clock(ahb_clock, STM32_APB1_PRESCALER); + break; + case STM32_CLOCK_BUS_APB2: + *rate = get_bus_clock(ahb_clock, STM32_APB2_PRESCALER); + break; + case STM32_CLOCK_BUS_APB4: + case STM32_CLOCK_BUS_APB4_2: + *rate = get_bus_clock(ahb_clock, STM32_APB4_PRESCALER); + break; + case STM32_CLOCK_BUS_APB5: + *rate = get_bus_clock(ahb_clock, STM32_APB5_PRESCALER); + break; +#if defined(STM32_LSE_ENABLED) + case STM32_SRC_LSE: + *rate = STM32_LSE_FREQ; + break; +#endif /* STM32_LSE_ENABLED */ +#if defined(STM32_LSI_ENABLED) + case STM32_SRC_LSI: + *rate = STM32_LSI_FREQ; + break; +#endif /* STM32_LSI_ENABLED */ +#if defined(STM32_HSE_ENABLED) + case STM32_SRC_HSE: + *rate = STM32_HSE_FREQ; + break; +#endif /* STM32_HSE_ENABLED */ +#if defined(STM32_HSI_ENABLED) + case STM32_SRC_HSI: + *rate = STM32_HSI_FREQ; + break; +#endif /* STM32_HSI_ENABLED */ + case STM32_SRC_PLL1: + *rate = get_pllout_frequency(PLL1_ID); + break; + case STM32_SRC_PLL2: + *rate = get_pllout_frequency(PLL2_ID); + break; + case STM32_SRC_PLL3: + *rate = get_pllout_frequency(PLL3_ID); + break; + case STM32_SRC_PLL4: + *rate = get_pllout_frequency(PLL4_ID); + break; +#if defined(STM32_CKPER_ENABLED) + case STM32_SRC_CKPER: + *rate = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE); + break; +#endif /* STM32_CKPER_ENABLED */ +#if defined(STM32_IC1_ENABLED) + case STM32_SRC_IC1: + *rate = get_icout_frequency(LL_RCC_IC1_GetSource(), STM32_IC1_DIV); + break; +#endif /* STM32_IC1_ENABLED */ +#if defined(STM32_IC2_ENABLED) + case STM32_SRC_IC2: + *rate = get_icout_frequency(LL_RCC_IC2_GetSource(), STM32_IC2_DIV); + break; +#endif /* STM32_IC2_ENABLED */ +#if defined(STM32_IC3_ENABLED) + case STM32_SRC_IC3: + *rate = get_icout_frequency(LL_RCC_IC3_GetSource(), STM32_IC3_DIV); + break; +#endif /* STM32_IC3_ENABLED */ +#if defined(STM32_IC4_ENABLED) + case STM32_SRC_IC4: + *rate = get_icout_frequency(LL_RCC_IC4_GetSource(), STM32_IC4_DIV); + break; +#endif /* STM32_IC4_ENABLED */ +#if defined(STM32_IC5_ENABLED) + case STM32_SRC_IC5: + *rate = get_icout_frequency(LL_RCC_IC5_GetSource(), STM32_IC5_DIV); + break; +#endif /* STM32_IC5_ENABLED */ +#if defined(STM32_IC6_ENABLED) + case STM32_SRC_IC6: + *rate = get_icout_frequency(LL_RCC_IC6_GetSource(), STM32_IC6_DIV); + break; +#endif /* STM32_IC6_ENABLED */ +#if defined(STM32_IC7_ENABLED) + case STM32_SRC_IC7: + *rate = get_icout_frequency(LL_RCC_IC7_GetSource(), STM32_IC7_DIV); + break; +#endif /* STM32_IC7_ENABLED */ +#if defined(STM32_IC8_ENABLED) + case STM32_SRC_IC8: + *rate = get_icout_frequency(LL_RCC_IC8_GetSource(), STM32_IC8_DIV); + break; +#endif /* STM32_IC8_ENABLED */ +#if defined(STM32_IC9_ENABLED) + case STM32_SRC_IC9: + *rate = get_icout_frequency(LL_RCC_IC9_GetSource(), STM32_IC9_DIV); + break; +#endif /* STM32_IC9_ENABLED */ +#if defined(STM32_IC10_ENABLED) + case STM32_SRC_IC10: + *rate = get_icout_frequency(LL_RCC_IC10_GetSource(), STM32_IC10_DIV); + break; +#endif /* STM32_IC10_ENABLED */ +#if defined(STM32_IC11_ENABLED) + case STM32_SRC_IC11: + *rate = get_icout_frequency(LL_RCC_IC11_GetSource(), STM32_IC11_DIV); + break; +#endif /* STM32_IC11_ENABLED */ +#if defined(STM32_IC12_ENABLED) + case STM32_SRC_IC12: + *rate = get_icout_frequency(LL_RCC_IC12_GetSource(), STM32_IC12_DIV); + break; +#endif /* STM32_IC12_ENABLED */ +#if defined(STM32_IC13_ENABLED) + case STM32_SRC_IC13: + *rate = get_icout_frequency(LL_RCC_IC13_GetSource(), STM32_IC13_DIV); + break; +#endif /* STM32_IC13_ENABLED */ +#if defined(STM32_IC14_ENABLED) + case STM32_SRC_IC14: + *rate = get_icout_frequency(LL_RCC_IC14_GetSource(), STM32_IC14_DIV); + break; +#endif /* STM32_IC14_ENABLED */ +#if defined(STM32_IC15_ENABLED) + case STM32_SRC_IC15: + *rate = get_icout_frequency(LL_RCC_IC15_GetSource(), STM32_IC15_DIV); + break; +#endif /* STM32_IC15_ENABLED */ +#if defined(STM32_IC16_ENABLED) + case STM32_SRC_IC16: + *rate = get_icout_frequency(LL_RCC_IC16_GetSource(), STM32_IC16_DIV); + break; +#endif /* STM32_IC16_ENABLED */ +#if defined(STM32_IC17_ENABLED) + case STM32_SRC_IC17: + *rate = get_icout_frequency(LL_RCC_IC17_GetSource(), STM32_IC17_DIV); + break; +#endif /* STM32_IC17_ENABLED */ +#if defined(STM32_IC18_ENABLED) + case STM32_SRC_IC18: + *rate = get_icout_frequency(LL_RCC_IC18_GetSource(), STM32_IC18_DIV); + break; +#endif /* STM32_IC18_ENABLED */ +#if defined(STM32_IC19_ENABLED) + case STM32_SRC_IC19: + *rate = get_icout_frequency(LL_RCC_IC19_GetSource(), STM32_IC19_DIV); + break; +#endif /* STM32_IC19_ENABLED */ +#if defined(STM32_IC20_ENABLED) + case STM32_SRC_IC20: + *rate = get_icout_frequency(LL_RCC_IC20_GetSource(), STM32_IC20_DIV); + break; +#endif /* STM32_IC20_ENABLED */ + default: + return -ENOTSUP; + } + + if (pclken->div) { + *rate /= (pclken->div + 1); + } + + return 0; +} + +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, + .configure = stm32_clock_control_configure, +}; + +/* + * Unconditionally switch the system clock source to HSI. + */ +__unused +static void stm32_clock_switch_to_hsi(void) +{ + /* Enable HSI if not enabled */ + if (LL_RCC_HSI_IsReady() != 1) { + /* Enable HSI */ + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1) { + /* Wait for HSI ready */ + } + } + + /* Set HSI as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { + } + + LL_RCC_SetCpuClkSource(LL_RCC_CPU_CLKSOURCE_HSI); + while (LL_RCC_GetCpuClkSource() != LL_RCC_CPU_CLKSOURCE_STATUS_HSI) { + } +} + +static int set_up_ics(void) +{ +#if defined(STM32_IC1_ENABLED) + LL_RCC_IC1_SetSource(ic_src_pll(STM32_IC1_PLL_SRC)); + LL_RCC_IC1_SetDivider(STM32_IC1_DIV); + LL_RCC_IC1_Enable(); +#endif + +#if defined(STM32_IC2_ENABLED) + LL_RCC_IC2_SetSource(ic_src_pll(STM32_IC2_PLL_SRC)); + LL_RCC_IC2_SetDivider(STM32_IC2_DIV); + LL_RCC_IC2_Enable(); +#endif + +#if defined(STM32_IC3_ENABLED) + LL_RCC_IC3_SetSource(ic_src_pll(STM32_IC3_PLL_SRC)); + LL_RCC_IC3_SetDivider(STM32_IC3_DIV); + LL_RCC_IC3_Enable(); +#endif + +#if defined(STM32_IC4_ENABLED) + LL_RCC_IC4_SetSource(ic_src_pll(STM32_IC4_PLL_SRC)); + LL_RCC_IC4_SetDivider(STM32_IC4_DIV); + LL_RCC_IC4_Enable(); +#endif + +#if defined(STM32_IC5_ENABLED) + LL_RCC_IC5_SetSource(ic_src_pll(STM32_IC5_PLL_SRC)); + LL_RCC_IC5_SetDivider(STM32_IC5_DIV); + LL_RCC_IC5_Enable(); +#endif + +#if defined(STM32_IC6_ENABLED) + LL_RCC_IC6_SetSource(ic_src_pll(STM32_IC6_PLL_SRC)); + LL_RCC_IC6_SetDivider(STM32_IC6_DIV); + LL_RCC_IC6_Enable(); +#endif + +#if defined(STM32_IC7_ENABLED) + LL_RCC_IC7_SetSource(ic_src_pll(STM32_IC7_PLL_SRC)); + LL_RCC_IC7_SetDivider(STM32_IC7_DIV); + LL_RCC_IC7_Enable(); +#endif + +#if defined(STM32_IC8_ENABLED) + LL_RCC_IC8_SetSource(ic_src_pll(STM32_IC8_PLL_SRC)); + LL_RCC_IC8_SetDivider(STM32_IC8_DIV); + LL_RCC_IC8_Enable(); +#endif + +#if defined(STM32_IC9_ENABLED) + LL_RCC_IC9_SetSource(ic_src_pll(STM32_IC9_PLL_SRC)); + LL_RCC_IC9_SetDivider(STM32_IC9_DIV); + LL_RCC_IC9_Enable(); +#endif + +#if defined(STM32_IC10_ENABLED) + LL_RCC_IC10_SetSource(ic_src_pll(STM32_IC10_PLL_SRC)); + LL_RCC_IC10_SetDivider(STM32_IC10_DIV); + LL_RCC_IC10_Enable(); +#endif + +#if defined(STM32_IC11_ENABLED) + LL_RCC_IC11_SetSource(ic_src_pll(STM32_IC11_PLL_SRC)); + LL_RCC_IC11_SetDivider(STM32_IC11_DIV); + LL_RCC_IC11_Enable(); +#endif + +#if defined(STM32_IC12_ENABLED) + LL_RCC_IC12_SetSource(ic_src_pll(STM32_IC12_PLL_SRC)); + LL_RCC_IC12_SetDivider(STM32_IC12_DIV); + LL_RCC_IC12_Enable(); +#endif + +#if defined(STM32_IC13_ENABLED) + LL_RCC_IC13_SetSource(ic_src_pll(STM32_IC13_PLL_SRC)); + LL_RCC_IC13_SetDivider(STM32_IC13_DIV); + LL_RCC_IC13_Enable(); +#endif + +#if defined(STM32_IC14_ENABLED) + LL_RCC_IC14_SetSource(ic_src_pll(STM32_IC14_PLL_SRC)); + LL_RCC_IC14_SetDivider(STM32_IC14_DIV); + LL_RCC_IC14_Enable(); +#endif + +#if defined(STM32_IC15_ENABLED) + LL_RCC_IC15_SetSource(ic_src_pll(STM32_IC15_PLL_SRC)); + LL_RCC_IC15_SetDivider(STM32_IC15_DIV); + LL_RCC_IC15_Enable(); +#endif + +#if defined(STM32_IC16_ENABLED) + LL_RCC_IC16_SetSource(ic_src_pll(STM32_IC16_PLL_SRC)); + LL_RCC_IC16_SetDivider(STM32_IC16_DIV); + LL_RCC_IC16_Enable(); +#endif + +#if defined(STM32_IC17_ENABLED) + LL_RCC_IC17_SetSource(ic_src_pll(STM32_IC17_PLL_SRC)); + LL_RCC_IC17_SetDivider(STM32_IC17_DIV); + LL_RCC_IC17_Enable(); +#endif + +#if defined(STM32_IC18_ENABLED) + LL_RCC_IC18_SetSource(ic_src_pll(STM32_IC18_PLL_SRC)); + LL_RCC_IC18_SetDivider(STM32_IC18_DIV); + LL_RCC_IC18_Enable(); +#endif + +#if defined(STM32_IC19_ENABLED) + LL_RCC_IC19_SetSource(ic_src_pll(STM32_IC19_PLL_SRC)); + LL_RCC_IC19_SetDivider(STM32_IC19_DIV); + LL_RCC_IC19_Enable(); +#endif + +#if defined(STM32_IC20_ENABLED) + LL_RCC_IC20_SetSource(ic_src_pll(STM32_IC20_PLL_SRC)); + LL_RCC_IC20_SetDivider(STM32_IC20_DIV); + LL_RCC_IC20_Enable(); +#endif + + return 0; +} + +static int set_up_plls(void) +{ +#if defined(STM32_PLL1_ENABLED) + /* TODO: Do not switch systematically on HSI if not needed */ + stm32_clock_switch_to_hsi(); + + LL_RCC_PLL1_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSI */ + if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL1 modulation spread-spectrum */ + LL_RCC_PLL1_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL1_IsEnabledBypass()) { + LL_RCC_PLL1_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL1_SetM(STM32_PLL1_M_DIVISOR); + LL_RCC_PLL1_SetN(STM32_PLL1_N_MULTIPLIER); + LL_RCC_PLL1_SetP1(STM32_PLL1_P1_DIVISOR); + LL_RCC_PLL1_SetP2(STM32_PLL1_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL1_SetFRACN(0); + LL_RCC_PLL1_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL1_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL1P_IsEnabled()) { + LL_RCC_PLL1P_Enable(); + } + + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1U) { + } +#endif /* STM32_PLL1_ENABLED */ + +#if defined(STM32_PLL2_ENABLED) + LL_RCC_PLL2_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSI */ + if (IS_ENABLED(STM32_PLL2_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL2_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL2_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL2_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL2_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL2_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL2 modulation spread-spectrum */ + LL_RCC_PLL2_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL2_IsEnabledBypass()) { + LL_RCC_PLL2_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR); + LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER); + LL_RCC_PLL2_SetP1(STM32_PLL2_P1_DIVISOR); + LL_RCC_PLL2_SetP2(STM32_PLL2_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL2_SetFRACN(0); + LL_RCC_PLL2_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL2_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL2P_IsEnabled()) { + LL_RCC_PLL2P_Enable(); + } + + LL_RCC_PLL2_Enable(); + while (LL_RCC_PLL2_IsReady() != 1U) { + } +#endif + +#if defined(STM32_PLL3_ENABLED) + LL_RCC_PLL3_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSIS */ + if (IS_ENABLED(STM32_PLL3_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL3_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL3_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL3_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL3_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL3_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL3 modulation spread-spectrum */ + LL_RCC_PLL3_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL3_IsEnabledBypass()) { + LL_RCC_PLL3_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL3_SetM(STM32_PLL3_M_DIVISOR); + LL_RCC_PLL3_SetN(STM32_PLL3_N_MULTIPLIER); + LL_RCC_PLL3_SetP1(STM32_PLL3_P1_DIVISOR); + LL_RCC_PLL3_SetP2(STM32_PLL3_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL3_SetFRACN(0); + LL_RCC_PLL3_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL3_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL3P_IsEnabled()) { + LL_RCC_PLL3P_Enable(); + } + + LL_RCC_PLL3_Enable(); + while (LL_RCC_PLL3_IsReady() != 1U) { + } +#endif + +#if defined(STM32_PLL4_ENABLED) + LL_RCC_PLL4_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSIS */ + if (IS_ENABLED(STM32_PLL4_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL4_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL4_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL4_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL4_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL4_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL4 modulation spread-spectrum */ + LL_RCC_PLL4_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL4_IsEnabledBypass()) { + LL_RCC_PLL4_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL4_SetM(STM32_PLL4_M_DIVISOR); + LL_RCC_PLL4_SetN(STM32_PLL4_N_MULTIPLIER); + LL_RCC_PLL4_SetP1(STM32_PLL4_P1_DIVISOR); + LL_RCC_PLL4_SetP2(STM32_PLL4_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL4_SetFRACN(0); + LL_RCC_PLL4_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL4_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL4P_IsEnabled()) { + LL_RCC_PLL4P_Enable(); + } + + LL_RCC_PLL4_Enable(); + while (LL_RCC_PLL4_IsReady() != 1U) { + } +#endif + + return 0; +} + +static void set_up_fixed_clock_sources(void) +{ + if (IS_ENABLED(STM32_HSE_ENABLED)) { + /* Check if need to enable HSE bypass feature or not */ + if (IS_ENABLED(STM32_HSE_BYPASS)) { + LL_RCC_HSE_EnableBypass(); + } else { + LL_RCC_HSE_DisableBypass(); + } + + if (IS_ENABLED(STM32_HSE_DIV2)) { + LL_RCC_HSE_SelectHSEDiv2AsDiv2Clock(); + } else { + LL_RCC_HSE_SelectHSEAsDiv2Clock(); + } + + /* Enable HSE */ + LL_RCC_HSE_Enable(); + while (LL_RCC_HSE_IsReady() != 1) { + /* Wait for HSE ready */ + } + } + + if (IS_ENABLED(STM32_HSI_ENABLED)) { + /* Enable HSI oscillator */ + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1) { + } + /* HSI divider configuration */ + LL_RCC_HSI_SetDivider(hsi_divider(STM32_HSI_DIVISOR)); + } + + if (IS_ENABLED(STM32_LSE_ENABLED)) { + /* Enable the power interface clock */ + LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR); + + if (!LL_PWR_IsEnabledBkUpAccess()) { + /* Enable write access to Backup domain */ + LL_PWR_EnableBkUpAccess(); + while (!LL_PWR_IsEnabledBkUpAccess()) { + /* Wait for Backup domain access */ + } + } + + /* Configure driving capability */ + LL_RCC_LSE_SetDriveCapability(STM32_LSE_DRIVING << RCC_LSECFGR_LSEDRV_Pos); + + if (IS_ENABLED(STM32_LSE_BYPASS)) { + /* Configure LSE bypass */ + LL_RCC_LSE_EnableBypass(); + } + + /* Enable LSE Oscillator */ + LL_RCC_LSE_Enable(); + /* Wait for LSE ready */ + while (!LL_RCC_LSE_IsReady()) { + } + + LL_PWR_DisableBkUpAccess(); + } + + if (IS_ENABLED(STM32_LSI_ENABLED)) { + /* Enable LSI oscillator */ + LL_RCC_LSI_Enable(); + while (LL_RCC_LSI_IsReady() != 1) { + } + } +} + +int stm32_clock_control_init(const struct device *dev) +{ + int r = 0; + + ARG_UNUSED(dev); + + /* For now, enable clocks (including low_power ones) of all RAM */ + uint32_t all_ram = LL_MEM_AXISRAM1 | LL_MEM_AXISRAM2 | LL_MEM_AXISRAM3 | LL_MEM_AXISRAM4 | + LL_MEM_AXISRAM5 | LL_MEM_AXISRAM6 | LL_MEM_AHBSRAM1 | LL_MEM_AHBSRAM2 | + LL_MEM_BKPSRAM | LL_MEM_FLEXRAM | LL_MEM_CACHEAXIRAM | LL_MEM_VENCRAM; + LL_MEM_EnableClock(all_ram); + LL_MEM_EnableClockLowPower(all_ram); + + /* Set up individual enabled clocks */ + set_up_fixed_clock_sources(); + + /* Set up PLLs */ + r = set_up_plls(); + if (r < 0) { + return r; + } + + /* Preset the prescalers prior to chosing SYSCLK */ + /* Prevents APB clock to go over limits */ + /* Set buses (AHB, APB1, APB2, APB4 & APB5) prescalers */ + LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_AHB_PRESCALER)); + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); + LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_APB4_PRESCALER)); + LL_RCC_SetAPB5Prescaler(apb5_prescaler(STM32_APB5_PRESCALER)); + + if (IS_ENABLED(STM32_CKPER_ENABLED)) { + LL_MISC_EnableClock(LL_PER); + LL_MISC_EnableClockLowPower(LL_PER); + while (LL_MISC_IsEnabledClock(LL_PER) != 1) { + } + } + + /* Set up ICs */ + r = set_up_ics(); + if (r < 0) { + return r; + } + + /* Set up sys clock */ + if (IS_ENABLED(STM32_SYSCLK_SRC_HSE)) { + /* Set sysclk source to HSE */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); + while (LL_RCC_GetSysClkSource() != + LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { + } + } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSI)) { + /* Set sysclk source to HSI */ + stm32_clock_switch_to_hsi(); + } else if (IS_ENABLED(STM32_SYSCLK_SRC_IC2)) { + /* Set sysclk source to IC2 */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_IC2_IC6_IC11); + while (LL_RCC_GetSysClkSource() != + LL_RCC_SYS_CLKSOURCE_STATUS_IC2_IC6_IC11) { + } + } else { + return -ENOTSUP; + } + + /* Update CMSIS variable */ + SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + + return r; +} + +/** + * @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 a7974467d2e59..3ba8fe3449208 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -53,6 +53,8 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32H7RSX) #include +#elif defined(CONFIG_SOC_SERIES_STM32N6X) +#include #elif defined(CONFIG_SOC_SERIES_STM32U0X) #include #elif defined(CONFIG_SOC_SERIES_STM32U5X) @@ -72,6 +74,7 @@ #define STM32_APB1_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb1_prescaler) #define STM32_APB2_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define STM32_APB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb3_prescaler) +#define STM32_APB4_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb4_prescaler) #define STM32_APB5_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb5_prescaler) #define STM32_APB7_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb7_prescaler) #define STM32_AHB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb3_prescaler) @@ -141,6 +144,9 @@ #if DT_SAME_NODE(DT_RCC_CLOCKS_CTRL, DT_NODELABEL(clk_csi)) #define STM32_SYSCLK_SRC_CSI 1 #endif +#if DT_SAME_NODE(DT_RCC_CLOCKS_CTRL, DT_NODELABEL(ic2)) +#define STM32_SYSCLK_SRC_IC2 1 +#endif /** PLL node related symbols */ @@ -252,6 +258,38 @@ #define STM32_PLL2_PREDIV DT_PROP(DT_NODELABEL(pll2), prediv) #endif +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll1), st_stm32n6_pll_clock, okay) +#define STM32_PLL1_ENABLED 1 +#define STM32_PLL1_M_DIVISOR DT_PROP(DT_NODELABEL(pll1), div_m) +#define STM32_PLL1_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll1), mul_n) +#define STM32_PLL1_P1_DIVISOR DT_PROP(DT_NODELABEL(pll1), div_p1) +#define STM32_PLL1_P2_DIVISOR DT_PROP(DT_NODELABEL(pll1), div_p2) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32n6_pll_clock, okay) +#define STM32_PLL2_ENABLED 1 +#define STM32_PLL2_M_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_m) +#define STM32_PLL2_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll2), mul_n) +#define STM32_PLL2_P1_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_p1) +#define STM32_PLL2_P2_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_p2) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32n6_pll_clock, okay) +#define STM32_PLL3_ENABLED 1 +#define STM32_PLL3_M_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_m) +#define STM32_PLL3_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll3), mul_n) +#define STM32_PLL3_P1_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_p1) +#define STM32_PLL3_P2_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_p2) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll4), st_stm32n6_pll_clock, okay) +#define STM32_PLL4_ENABLED 1 +#define STM32_PLL4_M_DIVISOR DT_PROP(DT_NODELABEL(pll4), div_m) +#define STM32_PLL4_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll4), mul_n) +#define STM32_PLL4_P1_DIVISOR DT_PROP(DT_NODELABEL(pll4), div_p1) +#define STM32_PLL4_P2_DIVISOR DT_PROP(DT_NODELABEL(pll4), div_p2) +#endif + /** PLL/PLL1 clock source */ #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pll)) && \ DT_NODE_HAS_PROP(DT_NODELABEL(pll), clocks) @@ -281,6 +319,9 @@ #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pll2)) && \ DT_NODE_HAS_PROP(DT_NODELABEL(pll2), clocks) #define DT_PLL2_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pll2)) +#if DT_SAME_NODE(DT_PLL2_CLOCKS_CTRL, DT_NODELABEL(clk_msi)) +#define STM32_PLL2_SRC_MSI 1 +#endif #if DT_SAME_NODE(DT_PLL2_CLOCKS_CTRL, DT_NODELABEL(clk_msis)) #define STM32_PLL2_SRC_MSIS 1 #endif @@ -297,6 +338,9 @@ #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pll3)) && \ DT_NODE_HAS_PROP(DT_NODELABEL(pll3), clocks) #define DT_PLL3_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pll3)) +#if DT_SAME_NODE(DT_PLL3_CLOCKS_CTRL, DT_NODELABEL(clk_msi)) +#define STM32_PLL3_SRC_MSI 1 +#endif #if DT_SAME_NODE(DT_PLL3_CLOCKS_CTRL, DT_NODELABEL(clk_msis)) #define STM32_PLL3_SRC_MSIS 1 #endif @@ -309,6 +353,22 @@ #endif +/** PLL4 clock source */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(pll4), okay) && \ + DT_NODE_HAS_PROP(DT_NODELABEL(pll4), clocks) +#define DT_PLL4_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pll4)) +#if DT_SAME_NODE(DT_PLL4_CLOCKS_CTRL, DT_NODELABEL(clk_msi)) +#define STM32_PLL4_SRC_MSI 1 +#endif +#if DT_SAME_NODE(DT_PLL4_CLOCKS_CTRL, DT_NODELABEL(clk_hsi)) +#define STM32_PLL4_SRC_HSI 1 +#endif +#if DT_SAME_NODE(DT_PLL4_CLOCKS_CTRL, DT_NODELABEL(clk_hse)) +#define STM32_PLL4_SRC_HSE 1 +#endif + +#endif + /** Fixed clocks related symbols */ @@ -414,6 +474,11 @@ #define STM32_HSE_ENABLED 1 #define STM32_HSE_DIV2 DT_PROP(DT_NODELABEL(clk_hse), hse_div2) #define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) +#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32n6_hse_clock, okay) +#define STM32_HSE_ENABLED 1 +#define STM32_HSE_BYPASS DT_PROP(DT_NODELABEL(clk_hse), hse_bypass) +#define STM32_HSE_DIV2 DT_PROP(DT_NODELABEL(clk_hse), hse_div2) +#define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) #else #define STM32_HSE_FREQ 0 #endif @@ -431,6 +496,130 @@ #define STM32_CKPER_ENABLED 1 #endif +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(cpusw), st_stm32_clock_mux, okay) +#define STM32_CPUSW_ENABLED 1 +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic1), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC1_ENABLED 1 +#define STM32_IC1_PLL_SRC DT_PROP(DT_NODELABEL(ic1), pll_src) +#define STM32_IC1_DIV DT_PROP(DT_NODELABEL(ic1), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic2), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC2_ENABLED 1 +#define STM32_IC2_PLL_SRC DT_PROP(DT_NODELABEL(ic2), pll_src) +#define STM32_IC2_DIV DT_PROP(DT_NODELABEL(ic2), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic3), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC3_ENABLED 1 +#define STM32_IC3_PLL_SRC DT_PROP(DT_NODELABEL(ic3), pll_src) +#define STM32_IC3_DIV DT_PROP(DT_NODELABEL(ic3), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic4), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC4_ENABLED 1 +#define STM32_IC4_PLL_SRC DT_PROP(DT_NODELABEL(ic4), pll_src) +#define STM32_IC4_DIV DT_PROP(DT_NODELABEL(ic4), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic5), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC5_ENABLED 1 +#define STM32_IC5_PLL_SRC DT_PROP(DT_NODELABEL(ic5), pll_src) +#define STM32_IC5_DIV DT_PROP(DT_NODELABEL(ic5), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic6), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC6_ENABLED 1 +#define STM32_IC6_PLL_SRC DT_PROP(DT_NODELABEL(ic6), pll_src) +#define STM32_IC6_DIV DT_PROP(DT_NODELABEL(ic6), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic7), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC7_ENABLED 1 +#define STM32_IC7_PLL_SRC DT_PROP(DT_NODELABEL(ic7), pll_src) +#define STM32_IC7_DIV DT_PROP(DT_NODELABEL(ic7), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic8), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC8_ENABLED 1 +#define STM32_IC8_PLL_SRC DT_PROP(DT_NODELABEL(ic8), pll_src) +#define STM32_IC8_DIV DT_PROP(DT_NODELABEL(ic8), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic9), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC9_ENABLED 1 +#define STM32_IC9_PLL_SRC DT_PROP(DT_NODELABEL(ic9), pll_src) +#define STM32_IC9_DIV DT_PROP(DT_NODELABEL(ic9), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic10), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC10_ENABLED 1 +#define STM32_IC10_PLL_SRC DT_PROP(DT_NODELABEL(ic10), pll_src) +#define STM32_IC10_DIV DT_PROP(DT_NODELABEL(ic10), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic11), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC11_ENABLED 1 +#define STM32_IC11_PLL_SRC DT_PROP(DT_NODELABEL(ic11), pll_src) +#define STM32_IC11_DIV DT_PROP(DT_NODELABEL(ic11), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic12), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC12_ENABLED 1 +#define STM32_IC12_PLL_SRC DT_PROP(DT_NODELABEL(ic12), pll_src) +#define STM32_IC12_DIV DT_PROP(DT_NODELABEL(ic12), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic13), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC13_ENABLED 1 +#define STM32_IC13_PLL_SRC DT_PROP(DT_NODELABEL(ic13), pll_src) +#define STM32_IC13_DIV DT_PROP(DT_NODELABEL(ic13), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic14), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC14_ENABLED 1 +#define STM32_IC14_PLL_SRC DT_PROP(DT_NODELABEL(ic14), pll_src) +#define STM32_IC14_DIV DT_PROP(DT_NODELABEL(ic14), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic15), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC15_ENABLED 1 +#define STM32_IC15_PLL_SRC DT_PROP(DT_NODELABEL(ic15), pll_src) +#define STM32_IC15_DIV DT_PROP(DT_NODELABEL(ic15), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic16), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC16_ENABLED 1 +#define STM32_IC16_PLL_SRC DT_PROP(DT_NODELABEL(ic16), pll_src) +#define STM32_IC16_DIV DT_PROP(DT_NODELABEL(ic16), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic17), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC17_ENABLED 1 +#define STM32_IC17_PLL_SRC DT_PROP(DT_NODELABEL(ic17), pll_src) +#define STM32_IC17_DIV DT_PROP(DT_NODELABEL(ic17), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic18), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC18_ENABLED 1 +#define STM32_IC18_PLL_SRC DT_PROP(DT_NODELABEL(ic18), pll_src) +#define STM32_IC18_DIV DT_PROP(DT_NODELABEL(ic18), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic19), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC19_ENABLED 1 +#define STM32_IC19_PLL_SRC DT_PROP(DT_NODELABEL(ic19), pll_src) +#define STM32_IC19_DIV DT_PROP(DT_NODELABEL(ic19), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic20), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC20_ENABLED 1 +#define STM32_IC20_PLL_SRC DT_PROP(DT_NODELABEL(ic20), pll_src) +#define STM32_IC20_DIV DT_PROP(DT_NODELABEL(ic20), ic_div) +#endif + /** Driver structure definition */ struct stm32_pclken { diff --git a/include/zephyr/dt-bindings/clock/stm32_clock.h b/include/zephyr/dt-bindings/clock/stm32_clock.h index 37241a26c46dd..0564c3084b155 100644 --- a/include/zephyr/dt-bindings/clock/stm32_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32_clock.h @@ -22,6 +22,7 @@ #define STM32_CLOCK_BUS_APB5 12 #define STM32_CLOCK_BUS_AXI 13 #define STM32_CLOCK_BUS_MLAHB 14 +#define STM32_CLOCK_BUS_APB4_2 15 #define STM32_CLOCK_DIV_SHIFT 12 diff --git a/include/zephyr/dt-bindings/clock/stm32n6_clock.h b/include/zephyr/dt-bindings/clock/stm32n6_clock.h new file mode 100644 index 0000000000000..156ca1f27abe5 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32n6_clock.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32N6_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32N6_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/** Domain clocks */ + +/* RM0468, Table 56 Kernel clock distribution summary */ + +/** System clock */ +/* defined in stm32_common_clocks.h */ +/** Fixed clocks */ +#define STM32_SRC_HSE (STM32_SRC_LSI + 1) +#define STM32_SRC_HSI (STM32_SRC_HSE + 1) +#define STM32_SRC_MSI (STM32_SRC_HSI + 1) +/** PLL outputs */ +#define STM32_SRC_PLL1 (STM32_SRC_MSI + 1) +#define STM32_SRC_PLL2 (STM32_SRC_PLL1 + 1) +#define STM32_SRC_PLL3 (STM32_SRC_PLL2 + 1) +#define STM32_SRC_PLL4 (STM32_SRC_PLL3 + 1) +/** Clock muxes */ +#define STM32_SRC_CKPER (STM32_SRC_PLL4 + 1) +#define STM32_SRC_IC1 (STM32_SRC_CKPER + 1) +#define STM32_SRC_IC2 (STM32_SRC_IC1 + 1) +#define STM32_SRC_IC3 (STM32_SRC_IC2 + 1) +#define STM32_SRC_IC4 (STM32_SRC_IC3 + 1) +#define STM32_SRC_IC5 (STM32_SRC_IC4 + 1) +#define STM32_SRC_IC6 (STM32_SRC_IC5 + 1) +#define STM32_SRC_IC7 (STM32_SRC_IC6 + 1) +#define STM32_SRC_IC8 (STM32_SRC_IC7 + 1) +#define STM32_SRC_IC9 (STM32_SRC_IC8 + 1) +#define STM32_SRC_IC10 (STM32_SRC_IC9 + 1) +#define STM32_SRC_IC11 (STM32_SRC_IC10 + 1) +#define STM32_SRC_IC12 (STM32_SRC_IC11 + 1) +#define STM32_SRC_IC13 (STM32_SRC_IC12 + 1) +#define STM32_SRC_IC14 (STM32_SRC_IC13 + 1) +#define STM32_SRC_IC15 (STM32_SRC_IC14 + 1) +#define STM32_SRC_IC16 (STM32_SRC_IC15 + 1) +#define STM32_SRC_IC17 (STM32_SRC_IC16 + 1) +#define STM32_SRC_IC18 (STM32_SRC_IC17 + 1) +#define STM32_SRC_IC19 (STM32_SRC_IC18 + 1) +#define STM32_SRC_IC20 (STM32_SRC_IC19 + 1) + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x250 +#define STM32_CLOCK_BUS_AHB2 0x254 +#define STM32_CLOCK_BUS_AHB3 0x258 +#define STM32_CLOCK_BUS_AHB4 0x25C +#define STM32_CLOCK_BUS_AHB5 0x260 +#define STM32_CLOCK_BUS_APB1 0x264 +#define STM32_CLOCK_BUS_APB1_2 0x268 +#define STM32_CLOCK_BUS_APB2 0x26C +#define STM32_CLOCK_BUS_APB3 0x270 +#define STM32_CLOCK_BUS_APB4 0x274 +#define STM32_CLOCK_BUS_APB4_2 0x278 +#define STM32_CLOCK_BUS_APB5 0x27C + +#define STM32_CLOCK_LP_BUS_SHIFT 0x40 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB5 + +#define STM32_CLOCK_REG_MASK 0xFFFU +#define STM32_CLOCK_REG_SHIFT 0U +#define STM32_CLOCK_SHIFT_MASK 0x1FU +#define STM32_CLOCK_SHIFT_SHIFT 12U +#define STM32_CLOCK_MASK_MASK 0x7U +#define STM32_CLOCK_MASK_SHIFT 17U +#define STM32_CLOCK_VAL_MASK 0x7U +#define STM32_CLOCK_VAL_SHIFT 20U + +/** + * @brief STM32U5 clock configuration bit field. + * + * - reg (1/2/3) [ 0 : 11 ] + * - shift (0..31) [ 12 : 16 ] + * - mask (0x1, 0x3, 0x7) [ 17 : 19 ] + * - val (0..7) [ 20 : 22 ] + * + * @param reg RCC_CCIPRx register offset + * @param shift Position within RCC_CCIPRx. + * @param mask Mask for the RCC_CCIPRx field. + * @param val Clock value (0, 1, ... 7). + */ +#define STM32_DOMAIN_CLOCK(val, mask, shift, reg) \ + ((((reg) & STM32_CLOCK_REG_MASK) << STM32_CLOCK_REG_SHIFT) | \ + (((shift) & STM32_CLOCK_SHIFT_MASK) << STM32_CLOCK_SHIFT_SHIFT) | \ + (((mask) & STM32_CLOCK_MASK_MASK) << STM32_CLOCK_MASK_SHIFT) | \ + (((val) & STM32_CLOCK_VAL_MASK) << STM32_CLOCK_VAL_SHIFT)) + +/** @brief RCC_CCIPRx register offset (RM0468.pdf) */ +#define CCIPR1_REG 0x144 +#define CCIPR2_REG 0x148 +#define CCIPR3_REG 0x14C +#define CCIPR4_REG 0x150 +#define CCIPR5_REG 0x154 +#define CCIPR6_REG 0x158 +#define CCIPR7_REG 0x15C +#define CCIPR8_REG 0x160 +#define CCIPR9_REG 0x164 +#define CCIPR12_REG 0x170 +#define CCIPR13_REG 0x174 +#define CCIPR14_REG 0x178 + +/** @brief Device domain clocks selection helpers */ +/** CCIPR1 devices */ +#define ADF1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR1_REG) +#define ADC12_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR1_REG) +#define DCMIPP_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 20, CCIPR1_REG) +/** CCIPR2 devices */ +#define ETH1PTP_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR2_REG) +#define ETH1CLK_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 12, CCIPR2_REG) +#define ETH1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR2_REG) +#define ETH1REFCLK_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 20, CCIPR2_REG) +#define ETH1GTXCLK_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 24, CCIPR2_REG) +/** CCIPR3 devices */ +#define FDCAN_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR3_REG) +#define FMC_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR3_REG) +/** CCIPR4 devices */ +#define I2C1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR4_REG) +#define I2C2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR4_REG) +#define I2C3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR4_REG) +#define I2C4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR4_REG) +#define I3C1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR4_REG) +#define I3C2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR4_REG) +#define LTDC_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 24, CCIPR4_REG) +/** CCIPR5 devices */ +#define MCO1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR5_REG) +#define MCO2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR5_REG) +#define MDF1SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR5_REG) +/** CCIPR6 devices */ +#define XSPI1_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR6_REG) +#define XSPI2_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR6_REG) +#define XSPI3_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 8, CCIPR6_REG) +#define OTGPHY1_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 12, CCIPR6_REG) +#define OTGPHY1CKREF_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 16, CCIPR6_REG) +#define OTGPHY2_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 20, CCIPR6_REG) +#define OTGPHY2CKREF_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 24, CCIPR6_REG) +/** CCIPR7 devices */ +#define PER_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR7_REG) +#define PSSI_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR7_REG) +#define RTC_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 8, CCIPR7_REG) +#define SAI1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR7_REG) +#define SAI2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR7_REG) +/** CCIPR8 devices */ +#define SDMMC1_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR8_REG) +#define SDMMC2_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR8_REG) +/** CCIPR9 devices */ +#define SPDIFRX1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR9_REG) +#define SPI1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR9_REG) +#define SPI2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR9_REG) +#define SPI3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR9_REG) +#define SPI4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR9_REG) +#define SPI5_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR9_REG) +#define SPI6_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR9_REG) +/** CCIPR12 devices */ +#define LPTIM1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR12_REG) +#define LPTIM2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR12_REG) +#define LPTIM3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR12_REG) +#define LPTIM4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR12_REG) +#define LPTIM5_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR12_REG) +/** CCIPR13 devices */ +#define USART1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR13_REG) +#define USART2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR13_REG) +#define USART3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR13_REG) +#define UART4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR13_REG) +#define UART5_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR13_REG) +#define USART6_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR13_REG) +#define UART7_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR13_REG) +#define UART8_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 28, CCIPR13_REG) +/** CCIPR14 devices */ +#define UART9_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR14_REG) +#define USART10_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR14_REG) +#define LPUART1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR14_REG) + +/** @brief RCC_ICxCFGR register offset (RM0468.pdf) */ +#define ICxCFGR_REG(ic) (0xC4 + ((ic) - 1) * 4) + +/** @brief Divider ICx source selection */ +#define ICx_PLLy_SEL(ic, pll) STM32_DOMAIN_CLOCK((pll) - 1, 3, 28, ICxCFGR_REG(ic)) + +/** @brief RCC_CFGR1 register offset (RM0468.pdf) */ +#define CFGR1_REG 0x20 + +/** @brief CPU clock switch selection */ +#define CPU_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 16, CFGR1_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32N6_CLOCK_H_ */ From 6bf10b7bd6e8ee4f0b2f1aa530e5949c5766ca0e Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:21:15 +0100 Subject: [PATCH 07/15] drivers: pinctrl: stm32: add pinctrl for stm32n6 Add pinctrl driver for STM32N6 Signed-off-by: Guillaume Gautier --- drivers/pinctrl/pinctrl_stm32.c | 1 + include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h | 3 ++- include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index 9dc3e26f37cca..73668b0b284c5 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -63,6 +63,7 @@ static const struct device *const gpio_ports[] = { DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpion)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioo)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiop)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioq)), }; /** Number of GPIO ports. */ diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h index 0c5933c580e50..25b76bb2dd570 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h @@ -26,9 +26,10 @@ #define STM32_PORTN 13 #define STM32_PORTO 14 #define STM32_PORTP 15 /* IO port P (0xF) */ +#define STM32_PORTQ 16 /* IO port Q (0x10) */ #ifndef STM32_PORTS_MAX -#define STM32_PORTS_MAX (STM32_PORTP + 1) +#define STM32_PORTS_MAX (STM32_PORTQ + 1) #endif /** diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h index 52612f6948d51..aa055a5c3f73b 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h @@ -55,7 +55,7 @@ * - line [ 5 : 8 ] * - port [ 9 : 13 ] * - * @param port Port ('A'..'P') + * @param port Port ('A'..'Q') * @param line Pin (0..15) * @param mode Mode (ANALOG, GPIO_IN, ALTERNATE). */ From 83d717a169dd1cc6f0e4024f58c3aa203f887f3c Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:23:01 +0100 Subject: [PATCH 08/15] drivers: gpio: stm32: add support for stm32n6 Add GPIO support for STM32N6 Signed-off-by: Guillaume Gautier --- drivers/gpio/gpio_stm32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index 29b243b3d0616..79a09dd1238fe 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -772,3 +772,4 @@ GPIO_DEVICE_INIT_STM32_IF_OKAY(m, M); GPIO_DEVICE_INIT_STM32_IF_OKAY(n, N); GPIO_DEVICE_INIT_STM32_IF_OKAY(o, O); GPIO_DEVICE_INIT_STM32_IF_OKAY(p, P); +GPIO_DEVICE_INIT_STM32_IF_OKAY(q, Q); From b7d390fd5f2d22729c75f1abb8a05d9042c3e57e Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:23:08 +0100 Subject: [PATCH 09/15] include: zephyr: dt-bindings: reset: add stm32n6 Add STM32N6 dt bindings for reset Signed-off-by: Guillaume Gautier --- .../zephyr/dt-bindings/reset/stm32n6_reset.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/zephyr/dt-bindings/reset/stm32n6_reset.h diff --git a/include/zephyr/dt-bindings/reset/stm32n6_reset.h b/include/zephyr/dt-bindings/reset/stm32n6_reset.h new file mode 100644 index 0000000000000..0b645598f0862 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/stm32n6_reset.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32N6_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32N6_RESET_H_ + +#include "stm32-common.h" + +/* RCC bus reset register offset */ +#define STM32_RESET_BUS_AHB1 0x210 +#define STM32_RESET_BUS_AHB2 0x214 +#define STM32_RESET_BUS_AHB3 0x218 +#define STM32_RESET_BUS_AHB4 0x21C +#define STM32_RESET_BUS_AHB5 0x220 +#define STM32_RESET_BUS_APB1L 0x224 +#define STM32_RESET_BUS_APB1H 0x228 +#define STM32_RESET_BUS_APB2 0x22C +#define STM32_RESET_BUS_APB4L 0x234 +#define STM32_RESET_BUS_APB4H 0x238 +#define STM32_RESET_BUS_APB5 0x23C + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32N6_RESET_H_ */ From 16a7db4e948415addb796c62b049b71fc1997c02 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:23:58 +0100 Subject: [PATCH 10/15] dts: arm: st: n6: add dtsi for stm32n6 series Add dtsi files for STM32N6 series Signed-off-by: Guillaume Gautier --- dts/arm/st/n6/stm32n6.dtsi | 377 +++++++++++++++++++++++++++++++++ dts/arm/st/n6/stm32n657.dtsi | 14 ++ dts/arm/st/n6/stm32n657X0.dtsi | 17 ++ 3 files changed, 408 insertions(+) create mode 100644 dts/arm/st/n6/stm32n6.dtsi create mode 100644 dts/arm/st/n6/stm32n657.dtsi create mode 100644 dts/arm/st/n6/stm32n657X0.dtsi diff --git a/dts/arm/st/n6/stm32n6.dtsi b/dts/arm/st/n6/stm32n6.dtsi new file mode 100644 index 0000000000000..a6ad62cdaf34a --- /dev/null +++ b/dts/arm/st/n6/stm32n6.dtsi @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m55"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv8.1m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; + }; + + axisram1: memory@34000000 { + compatible = "mmio-sram"; + }; + + axisram2: memory@34180400 { + compatible = "mmio-sram"; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "st,stm32n6-hse-clock"; + status = "disabled"; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "st,stm32h7-hsi-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "st,stm32-lse-clock"; + clock-frequency = <32768>; + driving-capability = <2>; + status = "disabled"; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + pll1: pll: pll { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + pll2: pll2 { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + pll3: pll3 { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + pll4: pll4 { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + cpusw: cpusw { + #clock-cells = <0>; + compatible = "st,stm32n6-cpu-clock-mux", "st,stm32-clock-mux"; + status = "disabled"; + }; + + perck: perck { + #clock-cells = <0>; + compatible = "st,stm32-clock-mux"; + status = "disabled"; + }; + + ic1: ic1 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic2: ic2 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic3: ic3 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic4: ic4 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic5: ic5 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic6: ic6 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic7: ic7 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic8: ic8 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic9: ic9 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic10: ic10 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic11: ic11 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic12: ic12 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic13: ic13 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic14: ic14 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic15: ic15 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic16: ic16 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic17: ic17 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic18: ic18 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic19: ic19 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic20: ic20 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + }; + + soc { + rcc: rcc@56028000 { + compatible = "st,stm32n6-rcc"; + clocks-controller; + #clock-cells = <2>; + reg = <0x56028000 0x2000>; + + rctl: reset-controller { + compatible = "st,stm32-rcc-rctl"; + #reset-cells = <1>; + }; + }; + + exti: interrupt-controller@56025000 { + compatible = "st,stm32g0-exti", "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + reg = <0x56025000 0x400>; + num-lines = <16>; + interrupts = <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>, <33 0>, <34 0>, <35 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>; + }; + + pinctrl: pin-controller@56020000 { + compatible = "st,stm32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x56020000 0x2000>; + + gpioa: gpio@56020000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 0)>; + }; + + gpiob: gpio@56020400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 1)>; + }; + + gpioc: gpio@56020800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 2)>; + }; + + gpiod: gpio@56020c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020c00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 3)>; + }; + + gpioe: gpio@56021000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 4)>; + }; + + gpiof: gpio@56021400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 5)>; + }; + + gpiog: gpio@56021800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 6)>; + }; + + gpioh: gpio@56021c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021c00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 7)>; + }; + + gpion: gpio@56023400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56023400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 13)>; + }; + + gpioo: gpio@56023800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56023800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 14)>; + }; + + gpiop: gpio@56023c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56023C00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 15)>; + }; + + gpioq: gpio@56024000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56024000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 16)>; + }; + }; + + usart1: serial@52001000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001000 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 4)>; + resets = <&rctl STM32_RESET(APB2, 4)>; + interrupts = <159 0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/st/n6/stm32n657.dtsi b/dts/arm/st/n6/stm32n657.dtsi new file mode 100644 index 0000000000000..7cc6f02b17081 --- /dev/null +++ b/dts/arm/st/n6/stm32n657.dtsi @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +/ { + soc { + compatible = "st,stm32n657", "st,stm32n6", "simple-bus"; + }; +}; diff --git a/dts/arm/st/n6/stm32n657X0.dtsi b/dts/arm/st/n6/stm32n657X0.dtsi new file mode 100644 index 0000000000000..613c3ee443eb1 --- /dev/null +++ b/dts/arm/st/n6/stm32n657X0.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + axisram1: memory@34000000 { + reg = <0x34000000 DT_SIZE_K(624)>; + }; + + axisram2: memory@34180400 { + reg = <0x34180400 DT_SIZE_K(511)>; + }; +}; From 3cdd92e9ae67bd68f0701d7f7b47a8e37ccdfc8e Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Mon, 20 Jan 2025 09:24:23 +0100 Subject: [PATCH 11/15] soc: st: stm32: stm32n6x: add signing tool Generate signed binary necessary to start a program from Flash on STM32N6 Signed-off-by: Guillaume Gautier --- soc/st/stm32/stm32n6x/CMakeLists.txt | 17 +++++++++++++++++ soc/st/stm32/stm32n6x/Kconfig | 1 + 2 files changed, 18 insertions(+) diff --git a/soc/st/stm32/stm32n6x/CMakeLists.txt b/soc/st/stm32/stm32n6x/CMakeLists.txt index eebd281cd96be..008bb9440cd2a 100644 --- a/soc/st/stm32/stm32n6x/CMakeLists.txt +++ b/soc/st/stm32/stm32n6x/CMakeLists.txt @@ -8,3 +8,20 @@ zephyr_sources( zephyr_include_directories(.) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") + +if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) + set(SIGNING_TOOL STM32_SigningTool_CLI.exe) +else() + set(SIGNING_TOOL STM32_SigningTool_CLI) +endif() + +set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${SIGNING_TOOL} + -in ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin + -nk -t fsbl -hv 2.3 + -o ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.signed.bin + -dump ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.signed.bin + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} +) + +set_property(TARGET runners_yaml_props_target PROPERTY bin_file ${CONFIG_KERNEL_BIN_NAME}.signed.bin) diff --git a/soc/st/stm32/stm32n6x/Kconfig b/soc/st/stm32/stm32n6x/Kconfig index 853261ac18332..e8711ce26fd08 100644 --- a/soc/st/stm32/stm32n6x/Kconfig +++ b/soc/st/stm32/stm32n6x/Kconfig @@ -16,3 +16,4 @@ config SOC_SERIES_STM32N6X select INIT_ARCH_HW_AT_BOOT select SOC_RESET_HOOK select TRUSTED_EXECUTION_SECURE + select BUILD_OUTPUT_BIN From 671b0bcf4b97525ef570b944f656d3dd74c4ed10 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 20 Dec 2024 16:06:59 +0100 Subject: [PATCH 12/15] scripts: stm32cubeprogrammer: Add possibility to flash a bin file Add the option to flash a bin file if one is available from the board's cmake configuration. Use of elf has prio over this, and bin has prio over hex which remains the default option. Also add a parameter to stm32cubeprogrammer runner to specify the download address. Signed-off-by: Guillaume Gautier --- .../runners/stm32cubeprogrammer.py | 23 +++++++++- .../tests/test_stm32cubeprogrammer.py | 42 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/scripts/west_commands/runners/stm32cubeprogrammer.py b/scripts/west_commands/runners/stm32cubeprogrammer.py index 432d7431b76a2..a124e32d168f9 100644 --- a/scripts/west_commands/runners/stm32cubeprogrammer.py +++ b/scripts/west_commands/runners/stm32cubeprogrammer.py @@ -34,6 +34,7 @@ def __init__( port: str, frequency: int | None, reset_mode: str | None, + download_address: int | None, start_address: int | None, conn_modifiers: str | None, cli: Path | None, @@ -46,6 +47,7 @@ def __init__( self._port = port self._frequency = frequency + self._download_address = download_address self._start_address = start_address self._reset_mode = reset_mode self._conn_modifiers = conn_modifiers @@ -149,6 +151,15 @@ def do_add_parser(cls, parser): choices=["sw", "hw", "core"], help="Reset mode", ) + parser.add_argument( + "--download-address", + # To accept arguments in hex format, a wrapper lambda around int() must be used. + # Wrapping the lambda with functools.wraps() makes it so that 'invalid int value' + # is displayed when an invalid value is provided for this argument. + type=functools.wraps(int)(lambda s: int(s, base=0)), + required=False, + help="Address where flashing should be done" + ) parser.add_argument( "--start-address", # To accept arguments in hex format, a wrapper lambda around int() must be used. @@ -194,6 +205,7 @@ def do_create( port=args.port, frequency=args.frequency, reset_mode=args.reset_mode, + download_address=args.download_address, start_address=args.start_address, conn_modifiers=args.conn_modifiers, cli=args.cli, @@ -233,13 +245,22 @@ def flash(self, **kwargs) -> None: self.check_call(cmd + ["--erase", "all"]) # flash image and run application - dl_file = self.cfg.elf_file if self._use_elf else self.cfg.hex_file + if self._use_elf: + dl_file = self.cfg.elf_file + elif self.cfg.bin_file is not None and os.path.isfile(self.cfg.bin_file) and \ + "zephyr.signed" in self.cfg.bin_file: + dl_file = self.cfg.bin_file + elif self.cfg.hex_file is not None and os.path.isfile(self.cfg.hex_file): + # --user-elf not used and no bin file given, default to hex + dl_file = self.cfg.hex_file if dl_file is None: raise RuntimeError('cannot flash; no download file was specified') elif not os.path.isfile(dl_file): raise RuntimeError(f'download file {dl_file} does not exist') flash_and_run_args = ["--download", dl_file] + if self._download_address is not None: + flash_and_run_args.append(f"0x{self._download_address:X}") # '--start' is needed to start execution after flash. # The default start address is the beggining of the flash, diff --git a/scripts/west_commands/tests/test_stm32cubeprogrammer.py b/scripts/west_commands/tests/test_stm32cubeprogrammer.py index e574fd5327620..216e9233b55af 100644 --- a/scripts/west_commands/tests/test_stm32cubeprogrammer.py +++ b/scripts/west_commands/tests/test_stm32cubeprogrammer.py @@ -64,6 +64,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -88,6 +89,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": 0x8001000, "conn_modifiers": None, "cli": CLI_PATH, @@ -113,6 +115,7 @@ "port": "swd", "frequency": "4000", "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -137,6 +140,7 @@ "port": "swd", "frequency": None, "reset_mode": "hw", + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -161,6 +165,7 @@ "port": "swd", "frequency": None, "reset_mode": "sw", + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -185,6 +190,7 @@ "port": "swd", "frequency": None, "reset_mode": "core", + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -209,6 +215,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": "br=115200 sn=TEST", "cli": CLI_PATH, @@ -233,6 +240,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -257,6 +265,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -282,6 +291,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -307,6 +317,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": None, @@ -331,6 +342,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": None, @@ -355,6 +367,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": None, @@ -375,6 +388,32 @@ ], ], }, + { + "port": "swd", + "frequency": None, + "reset_mode": None, + "download_address": 0x80000000, + "start_address": None, + "conn_modifiers": None, + "cli": CLI_PATH, + "use_elf": False, + "erase": False, + "extload": None, + "tool_opt": [], + "system": "", + "cli_path": str(CLI_PATH), + "calls": [ + [ + str(CLI_PATH), + "--connect", + "port=swd", + "--download", + RC_KERNEL_HEX, + "0x80000000", + "--start", + ], + ], + }, ) """Test cases.""" @@ -400,6 +439,7 @@ def test_stm32cubeprogrammer_init( port=tc["port"], frequency=tc["frequency"], reset_mode=tc["reset_mode"], + download_address=tc["download_address"], start_address=tc["start_address"], conn_modifiers=tc["conn_modifiers"], cli=tc["cli"], @@ -436,6 +476,8 @@ def test_stm32cubeprogrammer_create( args.extend(["--frequency", tc["frequency"]]) if tc["reset_mode"]: args.extend(["--reset-mode", tc["reset_mode"]]) + if tc["download_address"]: + args.extend(["--download-address", str(tc["download_address"])]) if tc["start_address"]: args.extend(["--start-address", str(tc["start_address"])]) if tc["conn_modifiers"]: From 69c97057e0a8e9415bfbe3ccdf2399e55e83d675 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 22 Mar 2024 11:25:38 +0100 Subject: [PATCH 13/15] boards: st: stm32n6570_dk: add support for stm32n6570_dk board Add support for STM32N657 DK board. Signed-off-by: Guillaume Gautier --- boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk | 5 + boards/st/stm32n6570_dk/board.cmake | 9 + boards/st/stm32n6570_dk/board.yml | 6 + .../stm32n6570_dk/doc/img/stm32n6570_dk.webp | Bin 0 -> 11494 bytes boards/st/stm32n6570_dk/doc/index.rst | 188 ++++++++++++++++++ boards/st/stm32n6570_dk/stm32n6570_dk.dts | 108 ++++++++++ boards/st/stm32n6570_dk/stm32n6570_dk.yaml | 14 ++ .../st/stm32n6570_dk/stm32n6570_dk_defconfig | 15 ++ 8 files changed, 345 insertions(+) create mode 100644 boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk create mode 100644 boards/st/stm32n6570_dk/board.cmake create mode 100644 boards/st/stm32n6570_dk/board.yml create mode 100644 boards/st/stm32n6570_dk/doc/img/stm32n6570_dk.webp create mode 100644 boards/st/stm32n6570_dk/doc/index.rst create mode 100644 boards/st/stm32n6570_dk/stm32n6570_dk.dts create mode 100644 boards/st/stm32n6570_dk/stm32n6570_dk.yaml create mode 100644 boards/st/stm32n6570_dk/stm32n6570_dk_defconfig diff --git a/boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk b/boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk new file mode 100644 index 0000000000000..667266938964b --- /dev/null +++ b/boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk @@ -0,0 +1,5 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32N6570_DK + select SOC_STM32N657XX diff --git a/boards/st/stm32n6570_dk/board.cmake b/boards/st/stm32n6570_dk/board.cmake new file mode 100644 index 0000000000000..fbbb050642a77 --- /dev/null +++ b/boards/st/stm32n6570_dk/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +board_runner_args(stm32cubeprogrammer "--port=swd") +board_runner_args(stm32cubeprogrammer "--tool-opt= mode=HOTPLUG ap=1") +board_runner_args(stm32cubeprogrammer "--extload=MX66UW1G45G_STM32N6570-DK.stldr") +board_runner_args(stm32cubeprogrammer "--download-address=0x70000000") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/st/stm32n6570_dk/board.yml b/boards/st/stm32n6570_dk/board.yml new file mode 100644 index 0000000000000..04d7a92c5b05b --- /dev/null +++ b/boards/st/stm32n6570_dk/board.yml @@ -0,0 +1,6 @@ +board: + name: stm32n6570_dk + full_name: STM32N6570-DK + vendor: st + socs: + - name: stm32n657xx diff --git a/boards/st/stm32n6570_dk/doc/img/stm32n6570_dk.webp b/boards/st/stm32n6570_dk/doc/img/stm32n6570_dk.webp new file mode 100644 index 0000000000000000000000000000000000000000..a6788dc33283e8ae91cf97fc9639a395767cea6e GIT binary patch literal 11494 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 Mb<6*L68TU4FKpdi&Hw-a literal 0 HcmV?d00001 diff --git a/boards/st/stm32n6570_dk/doc/index.rst b/boards/st/stm32n6570_dk/doc/index.rst new file mode 100644 index 0000000000000..7b4218d2c8f03 --- /dev/null +++ b/boards/st/stm32n6570_dk/doc/index.rst @@ -0,0 +1,188 @@ +.. zephyr:board:: stm32n6570_dk + +Overview +******** + +The STM32N6570_DK Discovery kit is a complete demonstration and development platform +for the Arm® Cortex®‑M55 core‑based STM32N657X0H3Q microcontroller. + +The STM32N6570_DK Discovery kit includes a full range of hardware features that help +the user evaluate many peripherals, such as USB Type-C®, Octo‑SPI flash memory and +Hexadeca‑SPI PSRAM devices, Ethernet, camera module, LCD, microSD™, audio codec, +digital microphones, ADC, flexible extension connectors, and user button. +The four flexible extension connectors feature easy and unlimited expansion capabilities +for specific applications such as wireless connectivity, analog applications, and sensors. + +The STM32N657X0H3Q microcontroller features one USB 2.0 high‑speed/full‑speed +Device/Host/OTG controller, one USB 2.0 high‑speed/full‑speed Device/Host/OTG controller +with UCPD (USB Type-C® Power Delivery), one Ethernet with TSN (time-sensitive networking), +four I2Cs, two I3Cs, six SPIs (of which four I2S‑capable), two SAIs, with four DMIC support, +five USARTs, five UARTs (ISO78916 interface, LIN, IrDA, up to 12.5 Mbit/s), one LPUART, +two SDMMCs (MMC version 4.0, CE-ATA version 1.0, and SD version 1.0.1), three CAN FD +with TTCAN capability, JTAG and SWD debugging support, and Embedded Trace Macrocell™ (ETM). + +The STM32N6570_DK Discovery kit integrates an STLINK-V3EC embedded in-circuit debugger and +programmer for the STM32 MCU, with a USB Virtual COM port bridge and the comprehensive MCU Package. + +Hardware +******** + +- STM32N657X0H3Q Arm® Cortex®‑M55‑based microcontroller featuring ST Neural-ART Accelerator, + H264 encoder, NeoChrom 2.5D GPU, and 4.2 Mbytes of contiguous SRAM, in a VFBGA264 package +- 5" LCD module with capacitive touch panel +- USB Type-C® with USB 2.0 HS interface, dual‑role‑power (DRP) +- USB Type-A with USB 2.0 HS interface, host, 0.5 A max +- 1‑Gbit Ethernet with TSN (time-sensitive networking) compliant with IEEE‑802.3‑2002 +- SAI audio codec +- One MEMS digital microphone +- 1‑Gbit Octo‑SPI flash memory +- 256-Mbit Hexadeca‑SPI PSRAM +- Two user LEDs +- User, tamper, and reset push-buttons +- Board connectors: + + - USB Type-C® + - USB Type-A + - Ethernet RJ45 + - Camera module + - microSD™ card + - LCD + - Stereo headset jack including analog microphone input + - Audio MEMS daughterboard expansion connector + - ARDUINO® Uno R3 expansion connector + - STMod+ expansion connector + +- On-board STLINK-V3EC debugger/programmer with USB re-enumeration capability: + Virtual COM port, and debug port + + +Supported Features +================== + +The Zephyr ``stm32n6570_dk`` board supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/st/stm32n6570_dk/stm32n6570_dk_defconfig` + + +Connections and IOs +=================== + +STM32N6570_DK Board has 12 GPIO controllers. These controllers are responsible +for pin muxing, input/output, pull-up, etc. + +For more details please refer to `STM32N6570_DK User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- LD1 : PO1 +- LD2 : PG10 +- USART_1_TX : PE5 +- USART_1_RX : PE6 + +System Clock +------------ + +STM32N6570_DK System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +400MHz, driven by 64MHz high speed internal oscillator. + +Serial Port +----------- + +STM32N6570_DK board has 10 U(S)ARTs. The Zephyr console output is assigned to +USART1. Default settings are 115200 8N1. + +Programming and Debugging +************************* + +STM32N6570_DK board includes an ST-LINK/V3 embedded debug tool interface. +This probe allows to flash the board using various tools. + +Flashing +======== + +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its :ref:`installation ` is required. +Version 2.18.0 or later of `STM32CubeProgrammer`_ is required. + +Flashing an application to STM32N6570_DK +------------------------------------------ + +Connect the STM32N6570_DK to your host computer using the USB port. +Then build and flash an application. + +.. note:: + For flashing, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on + the board. + + To run the application after flashing, BOOT1 should be set to 0 and the board + should be powered off and on again. + +Here is an example for the :zephyr:code-sample:`hello_world` application. + +Run a serial host program to connect with your Disco board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32n6570_dk + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! stm32n6570_dk/stm32n657xx + + +Debugging +========= + +For now debugging is only available through STM32CubeIDE: +* Go to File > Import and select C/C++ > STM32 Cortex-M Executable +* In Executable field, browse to your /build/zephyr/zephyr.elf +* In MCU field, select STM32N657X0HxQ. +* Click on Finish +* Then click on Debug to start the debugging session + +.. note:: + For debugging, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on the + board. + +.. _STM32N6570_DK website: + https://www.st.com/en/evaluation-tools/stm32n6570-dk.html + +.. _STM32N6570_DK User Manual: + https://www.st.com/resource/en/user_manual/um3300-discovery-kit-with-stm32n657x0-mcu-stmicroelectronics.pdf + +.. _STM32N657X0 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32n657x0.html + +.. _STM32N657 reference manual: + https://www.st.com/resource/en/reference_manual/rm0486-stm32n647657xx-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk.dts b/boards/st/stm32n6570_dk/stm32n6570_dk.dts new file mode 100644 index 0000000000000..94cd6ac702b02 --- /dev/null +++ b/boards/st/stm32n6570_dk/stm32n6570_dk.dts @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "STMicroelectronics STM32N6570 Discovery Kit board"; + compatible = "st,stm32n6570-dk"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &axisram2; + }; + + aliases { + led0 = &green_led_1; + }; + + leds: leds { + compatible = "gpio-leds"; + + green_led_1: led_1 { + gpios = <&gpioo 1 GPIO_ACTIVE_HIGH>; + label = "User LD1"; + }; + + red_led_1: led_2 { + gpios = <&gpiog 10 GPIO_ACTIVE_HIGH>; + label = "User LD2"; + }; + }; +}; + +&clk_hsi { + hsi-div = <1>; + status = "okay"; +}; + +&pll1 { + clocks = <&clk_hsi>; + div-m = <4>; + mul-n = <75>; + div-p1 = <1>; + div-p2 = <1>; + status = "okay"; +}; + +&ic1 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic2 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&ic6 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic11 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&perck { + clocks = <&rcc STM32_SRC_HSI PER_SEL(0)>; + status = "okay"; +}; + +&cpusw { + clocks = <&rcc STM32_SRC_IC1 CPU_SEL(3)>; + clock-frequency = ; + status = "okay"; +}; + +&rcc { + /* ic2, ic6 & ic11 must all be enabled to set ic2 as SYSCLK */ + clocks = <&ic2>; + clock-frequency = ; + ahb-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb4-prescaler = <1>; + apb5-prescaler = <1>; +}; + +&usart1 { + clocks = <&rcc STM32_CLOCK(APB2, 4)>, + <&rcc STM32_SRC_CKPER USART1_SEL(1)>; + pinctrl-0 = <&usart1_tx_pe5 &usart1_rx_pe6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk.yaml b/boards/st/stm32n6570_dk/stm32n6570_dk.yaml new file mode 100644 index 0000000000000..390fd67caa937 --- /dev/null +++ b/boards/st/stm32n6570_dk/stm32n6570_dk.yaml @@ -0,0 +1,14 @@ +identifier: stm32n6570_dk +name: STM32N6570 Discovery Kit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 1024 +flash: 0 +supported: + - gpio + - uart +vendor: st diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk_defconfig b/boards/st/stm32n6570_dk/stm32n6570_dk_defconfig new file mode 100644 index 0000000000000..5dfa1d198f0ab --- /dev/null +++ b/boards/st/stm32n6570_dk/stm32n6570_dk_defconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# No internal Flash +CONFIG_XIP=n From ec4fe41711bcbb4948adf5b79cd3d552a7e51080 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Wed, 29 May 2024 14:23:10 +0200 Subject: [PATCH 14/15] boards: st: Add support for the nucleo_n657x0_q Add support for the nucleo_n657x0_q board. Signed-off-by: Erwan Gouriou --- .../nucleo_n657x0_q/Kconfig.nucleo_n657x0_q | 7 + boards/st/nucleo_n657x0_q/board.cmake | 9 + boards/st/nucleo_n657x0_q/board.yml | 6 + .../doc/img/nucleo_n657x0_q.webp | Bin 0 -> 18466 bytes boards/st/nucleo_n657x0_q/doc/index.rst | 182 ++++++++++++++++++ boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts | 124 ++++++++++++ .../st/nucleo_n657x0_q/nucleo_n657x0_q.yaml | 14 ++ .../nucleo_n657x0_q/nucleo_n657x0_q_defconfig | 15 ++ 8 files changed, 357 insertions(+) create mode 100644 boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q create mode 100644 boards/st/nucleo_n657x0_q/board.cmake create mode 100644 boards/st/nucleo_n657x0_q/board.yml create mode 100644 boards/st/nucleo_n657x0_q/doc/img/nucleo_n657x0_q.webp create mode 100644 boards/st/nucleo_n657x0_q/doc/index.rst create mode 100644 boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts create mode 100644 boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml create mode 100644 boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig diff --git a/boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q b/boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q new file mode 100644 index 0000000000000..a1c2528a4709e --- /dev/null +++ b/boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q @@ -0,0 +1,7 @@ +# STM32N657X0_Q Nucleo board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_N657X0_Q + select SOC_STM32N657XX diff --git a/boards/st/nucleo_n657x0_q/board.cmake b/boards/st/nucleo_n657x0_q/board.cmake new file mode 100644 index 0000000000000..a285b0deabd18 --- /dev/null +++ b/boards/st/nucleo_n657x0_q/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +board_runner_args(stm32cubeprogrammer "--port=swd") +board_runner_args(stm32cubeprogrammer "--tool-opt= mode=HOTPLUG ap=1") +board_runner_args(stm32cubeprogrammer "--extload=MX25UM51245G_STM32N6570-NUCLEO.stldr") +board_runner_args(stm32cubeprogrammer "--download-address=0x70000000") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/st/nucleo_n657x0_q/board.yml b/boards/st/nucleo_n657x0_q/board.yml new file mode 100644 index 0000000000000..57f19a7e1fabb --- /dev/null +++ b/boards/st/nucleo_n657x0_q/board.yml @@ -0,0 +1,6 @@ +board: + name: nucleo_n657x0_q + full_name: Nucleo N657x0-Q + vendor: st + socs: + - name: stm32n657xx diff --git a/boards/st/nucleo_n657x0_q/doc/img/nucleo_n657x0_q.webp b/boards/st/nucleo_n657x0_q/doc/img/nucleo_n657x0_q.webp new file mode 100644 index 0000000000000000000000000000000000000000..c6d918de66d9c3db64e1f9924e6a22e6d2c29d94 GIT binary patch literal 18466 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 E0OJnjg#Z8m literal 0 HcmV?d00001 diff --git a/boards/st/nucleo_n657x0_q/doc/index.rst b/boards/st/nucleo_n657x0_q/doc/index.rst new file mode 100644 index 0000000000000..3ea57ffadd382 --- /dev/null +++ b/boards/st/nucleo_n657x0_q/doc/index.rst @@ -0,0 +1,182 @@ +.. zephyr:board:: nucleo_n657x0_q + +Overview +******** + +The STM32 Nucleo-144 board provides an affordable and flexible way for users to try out +new concepts and build prototypes by choosing from the various combinations of performance +and power consumption features, provided by the STM32 microcontroller. For the compatible boards, +the internal or external SMPS significantly reduces power consumption in Run mode. + +The ST Zio connector, which extends the ARDUINO® Uno V3 connectivity, and the ST morpho headers +provide an easy means of expanding the functionality of the Nucleo open development platform with +a wide choice of specialized shields. + +The STM32 Nucleo-144 board does not require any separate probe as it integrates the ST-LINK +debugger/programmer. + +The STM32 Nucleo-144 board comes with the STM32 comprehensive free software libraries and +examples available with the STM32Cube MCU Package. + +Hardware +******** + +- Common features: + + - STM32 microcontroller in an LQFP144, TFBGA225, or VFBGA264 package + - 3 user LEDs + - 1 user push-button and 1 reset push-button + - 32.768 kHz crystal oscillator + - Board connectors: + + - SWD + - ST morpho expansion connector + + - Flexible power-supply options: ST-LINK USB VBUS, USB connector, or external sources + +- Features specific to some of the boards (refer to the ordering information section + of the data brief for details); + + - External or internal SMPS to generate Vcore logic supply + - Ethernet compliant with IEEE-802.3-2002 + - USB Device only, USB OTG full speed, or SNK/UFP (full-speed or high-speed mode) + - Board connectors: + + - ARDUINO® Uno V3 connector or ST Zio expansion connector including ARDUINO® Uno V3 + - Camera module FPC + - MIPI20 compatible connector with trace signals + - USB with Micro-AB or USB Type-C® + - Ethernet RJ45 + + - On-board ST-LINK (STLINK/V2-1, STLINK-V3E, or STLINK-V3EC) debugger/programmer with + USB re-enumeration capability: mass storage, Virtual COM port, and debug port + +Supported Features +================== + +The Zephyr ``nucleo_n657x0_q`` board supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig` + + +Connections and IOs +=================== + +NUCLEO_N657X0_Q Board has 12 GPIO controllers. These controllers are responsible +for pin muxing, input/output, pull-up, etc. + +For more details please refer to `NUCLEO_N657X0_Q User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- LD1 : PO1 +- LD2 : PG10 +- USART_1_TX : PE5 +- USART_1_RX : PE6 + +System Clock +------------ + +NUCLEO_N657X0_Q System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +400MHz, driven by 64MHz high speed internal oscillator. + +Serial Port +----------- + +NUCLEO_N657X0_Q board has 10 U(S)ARTs. The Zephyr console output is assigned to +USART1. Default settings are 115200 8N1. + +Programming and Debugging +************************* + +NUCLEO_N657X0_Q board includes an ST-LINK/V3 embedded debug tool interface. +This probe allows to flash the board using various tools. + +Flashing +======== + +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its :ref:`installation ` is required. +Version 2.18.0 or later of `STM32CubeProgrammer`_ is required. + +Flashing an application to NUCLEO_N657X0_Q +------------------------------------------ + +Connect the NUCLEO_N657X0_Q to your host computer using the USB port. +Then build and flash an application. + +.. note:: + For flashing, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on + the board. + + To run the application after flashing, BOOT1 should be set to 0 and the board + should be powered off and on again. + +Here is an example for the :zephyr:code-sample:`hello_world` application. + +Run a serial host program to connect with your Nucleo board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nucleo_n657x0_q + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! nucleo_n657x0_q/stm32n657xx + +Debugging +========= + +For now debugging is only available through STM32CubeIDE: +* Go to File > Import and select C/C++ > STM32 Cortex-M Executable +* In Executable field, browse to your /build/zephyr/zephyr.elf +* In MCU field, select STM32N657X0HxQ. +* Click on Finish +* Then click on Debug to start the debugging session + +.. note:: + For debugging, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on the + board. + +.. _NUCLEO_N657X0_Q website: + https://www.st.com/en/evaluation-tools/nucleo-n657x0-q.html + +.. _NUCLEO_N657X0_Q User Manual: + https://www.st.com/resource/en/user_manual/um3417-stm32n6-nucleo144-board-mb1940-stmicroelectronics.pdf + +.. _STM32N657X0 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32n657x0.html + +.. _STM32N657 reference manual: + https://www.st.com/resource/en/reference_manual/rm0486-stm32n647657xx-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts new file mode 100644 index 0000000000000..92943cbfd52fa --- /dev/null +++ b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "STMicroelectronics STM32N657X0-Q-NUCLEO board"; + compatible = "st,stm32n657x0-q-nucleo"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &axisram2; + }; + + leds: leds { + compatible = "gpio-leds"; + + green_led: led_1 { + gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>; + label = "User LD6"; + }; + + blue_led: led_2 { + gpios = <&gpiog 8 GPIO_ACTIVE_HIGH>; + label = "User LD7"; + }; + + red_led: led_3 { + gpios = <&gpiog 10 GPIO_ACTIVE_HIGH>; + label = "User LD5"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_button: button_0 { + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + label = "User SB1"; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led; + sw0 = &user_button; + }; +}; + +&clk_hsi { + hsi-div = <1>; + status = "okay"; +}; + +&pll1 { + clocks = <&clk_hsi>; + div-m = <4>; + mul-n = <75>; + div-p1 = <1>; + div-p2 = <1>; + status = "okay"; +}; + +&ic1 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic2 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&ic6 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic11 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&perck { + clocks = <&rcc STM32_SRC_HSI PER_SEL(0)>; + status = "okay"; +}; + +&cpusw { + clocks = <&rcc STM32_SRC_IC1 CPU_SEL(3)>; + clock-frequency = ; + status = "okay"; +}; + +&rcc { + /* ic2, ic6 & ic11 must all be enabled to set ic2 as SYSCLK */ + clocks = <&ic2>; + clock-frequency = ; + ahb-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb4-prescaler = <1>; + apb5-prescaler = <1>; +}; + +&usart1 { + clocks = <&rcc STM32_CLOCK(APB2, 4)>, + <&rcc STM32_SRC_CKPER USART1_SEL(1)>; + pinctrl-0 = <&usart1_tx_pe5 &usart1_rx_pe6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; diff --git a/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml new file mode 100644 index 0000000000000..7e398f0d7fe91 --- /dev/null +++ b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml @@ -0,0 +1,14 @@ +identifier: nucleo_n657x0_q +name: ST Nucleo N657X0-Q +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 1024 +flash: 0 +supported: + - gpio + - uart +vendor: st diff --git a/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig new file mode 100644 index 0000000000000..5dfa1d198f0ab --- /dev/null +++ b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# No internal Flash +CONFIG_XIP=n From bd84fb8020369e00eb12fa96e386a08c0858b5ac Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Fri, 29 Mar 2024 09:20:24 +0100 Subject: [PATCH 15/15] dts: arm: st: n6: add all u(s)art instances Add U(S)ART2 to 10 to the device tree. Signed-off-by: Guillaume Gautier --- dts/arm/st/n6/stm32n6.dtsi | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/dts/arm/st/n6/stm32n6.dtsi b/dts/arm/st/n6/stm32n6.dtsi index a6ad62cdaf34a..f2e7dc8f47fd8 100644 --- a/dts/arm/st/n6/stm32n6.dtsi +++ b/dts/arm/st/n6/stm32n6.dtsi @@ -369,6 +369,87 @@ interrupts = <159 0>; status = "disabled"; }; + + usart2: serial@50004400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50004400 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 17)>; + resets = <&rctl STM32_RESET(APB1L, 17)>; + interrupts = <160 0>; + status = "disabled"; + }; + + usart3: serial@50004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50004800 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 18)>; + resets = <&rctl STM32_RESET(APB1L, 18)>; + interrupts = <161 0>; + status = "disabled"; + }; + + uart4: serial@50004c00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50004C00 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 19)>; + resets = <&rctl STM32_RESET(APB1L, 19)>; + interrupts = <162 0>; + status = "disabled"; + }; + + uart5: serial@50005000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50005000 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 20)>; + resets = <&rctl STM32_RESET(APB1L, 20)>; + interrupts = <163 0>; + status = "disabled"; + }; + + usart6: serial@52001400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001400 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 5)>; + resets = <&rctl STM32_RESET(APB2, 5)>; + interrupts = <164 0>; + status = "disabled"; + }; + + uart7: serial@50007800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50007800 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 30)>; + resets = <&rctl STM32_RESET(APB1L, 30)>; + interrupts = <165 0>; + status = "disabled"; + }; + + uart8: serial@50007c00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50007C00 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 31)>; + resets = <&rctl STM32_RESET(APB1L, 31)>; + interrupts = <166 0>; + status = "disabled"; + }; + + uart9: serial@52001800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001800 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 6)>; + resets = <&rctl STM32_RESET(APB2, 6)>; + interrupts = <167 0>; + status = "disabled"; + }; + + usart10: serial@52001c00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001C00 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 7)>; + resets = <&rctl STM32_RESET(APB2, 7)>; + interrupts = <168 0>; + status = "disabled"; + }; }; };