From 1edc4d045d5874638027da11da583cfcd0cb3bc5 Mon Sep 17 00:00:00 2001 From: Mario Paja Date: Mon, 15 Sep 2025 14:22:46 +0200 Subject: [PATCH 1/4] dt-bindings: clock: add stm32l5_clock This change introduces stm32l5xx clock definitions and separates it from L4xx series. This change comes because of CCIPR missmatch of SAI between L4xx and L5xx series. Signed-off-by: Mario Paja --- dts/arm/st/l5/stm32l5.dtsi | 3 +- .../clock_control/stm32_clock_control.h | 5 +- .../zephyr/dt-bindings/clock/stm32l4_clock.h | 2 +- .../zephyr/dt-bindings/clock/stm32l5_clock.h | 92 +++++++++++++++++++ 4 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 include/zephyr/dt-bindings/clock/stm32l5_clock.h diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index 4102b9b5088fe..e9b83d4bb3fea 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -2,12 +2,13 @@ * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2020 Linaro Limited * Copyright (c) 2024 STMicroelectronics + * Copyright (c) 2025 Mario Paja * * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include #include #include #include diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index 9b80fe60e24b1..ccce256482bfd 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -41,9 +41,10 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32L1X) #include -#elif defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) +#elif defined(CONFIG_SOC_SERIES_STM32L4X) #include +#elif defined(CONFIG_SOC_SERIES_STM32L5X) +#include #elif defined(CONFIG_SOC_SERIES_STM32MP2X) #include #elif defined(CONFIG_SOC_SERIES_STM32WBX) diff --git a/include/zephyr/dt-bindings/clock/stm32l4_clock.h b/include/zephyr/dt-bindings/clock/stm32l4_clock.h index 7fe6e514bce4c..cdef7de2b6426 100644 --- a/include/zephyr/dt-bindings/clock/stm32l4_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32l4_clock.h @@ -20,7 +20,7 @@ #define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB2 /** Domain clocks */ -/* RM0351/RM0432/RM0438, § Clock configuration register (RCC_CCIPRx) */ +/* RM0351/RM0432, § Clock configuration register (RCC_CCIPRx) */ /** System clock */ /* defined in stm32_common_clocks.h */ diff --git a/include/zephyr/dt-bindings/clock/stm32l5_clock.h b/include/zephyr/dt-bindings/clock/stm32l5_clock.h new file mode 100644 index 0000000000000..451f004b04085 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32l5_clock.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2025 Mario Paja + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L5_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L5_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x048 +#define STM32_CLOCK_BUS_AHB2 0x04c +#define STM32_CLOCK_BUS_AHB3 0x050 +#define STM32_CLOCK_BUS_APB1 0x058 +#define STM32_CLOCK_BUS_APB1_2 0x05c +#define STM32_CLOCK_BUS_APB2 0x060 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB2 + +/** Domain clocks */ +/* RM0438, § Clock configuration register (RCC_CCIPRx) */ + +/** System clock */ +/* defined in stm32_common_clocks.h */ +/** Fixed clocks */ +/* Low speed clocks defined in stm32_common_clocks.h */ +#define STM32_SRC_HSI (STM32_SRC_LSI + 1) +#define STM32_SRC_HSI48 (STM32_SRC_HSI + 1) +#define STM32_SRC_MSI (STM32_SRC_HSI48 + 1) +/** Bus clock */ +#define STM32_SRC_PCLK (STM32_SRC_MSI + 1) +#define STM32_SRC_TIMPCLK1 (STM32_SRC_PCLK + 1) +#define STM32_SRC_TIMPCLK2 (STM32_SRC_TIMPCLK1 + 1) +/** PLL clock outputs */ +#define STM32_SRC_PLL_P (STM32_SRC_TIMPCLK2 + 1) +#define STM32_SRC_PLL_Q (STM32_SRC_PLL_P + 1) +#define STM32_SRC_PLL_R (STM32_SRC_PLL_Q + 1) +/* PLLSAI1 clocks */ +#define STM32_SRC_PLLSAI1_P (STM32_SRC_PLL_R + 1) +#define STM32_SRC_PLLSAI1_Q (STM32_SRC_PLLSAI1_P + 1) +#define STM32_SRC_PLLSAI1_R (STM32_SRC_PLLSAI1_Q + 1) +/* PLLSAI2 clocks */ +#define STM32_SRC_PLLSAI2_P (STM32_SRC_PLLSAI1_R + 1) +#define STM32_SRC_PLLSAI2_Q (STM32_SRC_PLLSAI2_P + 1) +#define STM32_SRC_PLLSAI2_R (STM32_SRC_PLLSAI2_Q + 1) +#define STM32_SRC_PLLSAI2_DIVR (STM32_SRC_PLLSAI2_R + 1) + +/** @brief RCC_CCIPR register offset */ +#define CCIPR_REG 0x88 +#define CCIPR2_REG 0x9C + +/** @brief RCC_BDCR register offset */ +#define BDCR_REG 0x90 + +/** @brief RCC_CFGRx register offset */ +#define CFGR_REG 0x08 + +/** @brief Device domain clocks selection helpers */ +/** CCIPR devices */ +#define USART1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 0, CCIPR_REG) +#define USART2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 2, CCIPR_REG) +#define USART3_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 4, CCIPR_REG) +#define UART4_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 6, CCIPR_REG) +#define UART5_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 8, CCIPR_REG) +#define LPUART1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 10, CCIPR_REG) +#define I2C1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 12, CCIPR_REG) +#define I2C2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 14, CCIPR_REG) +#define I2C3_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 16, CCIPR_REG) +#define LPTIM1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 18, CCIPR_REG) +#define LPTIM2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 20, CCIPR_REG) +#define LPTIM3_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 22, CCIPR_REG) +#define FDCAN_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 24, CCIPR_REG) +#define CLK48_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 26, CCIPR_REG) +#define ADC_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 28, CCIPR_REG) +/** CCIPR2 devices */ +#define I2C4_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 0, CCIPR2_REG) +#define DFSDM_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 2, CCIPR2_REG) +#define ADFSDM_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 3, CCIPR2_REG) +#define SAI1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 5, CCIPR2_REG) +#define SAI2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 8, CCIPR2_REG) +#define SDMMC_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 14, CCIPR2_REG) +#define OSPI_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 20, CCIPR2_REG) + +/** BDCR devices */ +#define RTC_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 8, BDCR_REG) +/** CFGR devices */ +#define MCO1_SEL(val) STM32_DT_CLOCK_SELECT((val), 0xF, 24, CFGR_REG) +#define MCO1_PRE(val) STM32_DT_CLOCK_SELECT((val), 0x7, 28, CFGR_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L5_CLOCK_H_ */ From 318797daca073a90a1736a3f1777377ae97cbdbb Mon Sep 17 00:00:00 2001 From: Mario Paja Date: Mon, 15 Sep 2025 14:39:18 +0200 Subject: [PATCH 2/4] dts: st: l5: add sai1 nodes This change introduces PLLSAI1 and SAI1 A/B nodes to STM32L5xx series Signed-off-by: Mario Paja --- dts/arm/st/l5/stm32l5.dtsi | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index e9b83d4bb3fea..96d0691c0fb8e 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -121,6 +121,12 @@ compatible = "st,stm32l4-pll-clock"; status = "disabled"; }; + + pllsai1: pllsai1 { + #clock-cells = <0>; + compatible = "st,stm32l4-pllsai-clock"; + status = "disabled"; + }; }; soc { @@ -738,6 +744,30 @@ clocks = <&rcc STM32_CLOCK(AHB3, 0)>; status = "disabled"; }; + + sai1_a: sai1@40015404 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015404 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 21)>, + <&rcc STM32_SRC_PLLSAI1_P SAI1_SEL(0)>; + dmas = <&dma1 1 37 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS)>; + status = "disabled"; + }; + + sai1_b: sai1@40015424 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015424 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 21)>, + <&rcc STM32_SRC_PLLSAI1_P SAI1_SEL(0)>; + dmas = <&dma1 2 38 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS)>; + status = "disabled"; + }; }; die_temp: dietemp { From 33b42397862a4b7257a12c288c569bf24c018254 Mon Sep 17 00:00:00 2001 From: Mario Paja Date: Mon, 15 Sep 2025 15:20:18 +0200 Subject: [PATCH 3/4] drivers: i2s: stm32 sai add support for stm32l5xx series STM32L5xx series shares several DMA configurations with the other platforms. These changes aim to enable platform specific DMA configuration and align them to other platforms. Signed-off-by: Mario Paja --- drivers/i2s/i2s_stm32_sai.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2s/i2s_stm32_sai.c b/drivers/i2s/i2s_stm32_sai.c index dc41dd35fc1c7..e80fdd41dc425 100644 --- a/drivers/i2s/i2s_stm32_sai.c +++ b/drivers/i2s/i2s_stm32_sai.c @@ -287,7 +287,7 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) hdma->Init.Mode = DMA_NORMAL; #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) + defined(CONFIG_SOC_SERIES_STM32G4X) || defined(CONFIG_SOC_SERIES_STM32L5X) hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma->Init.Priority = DMA_PRIORITY_HIGH; @@ -312,7 +312,7 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; #if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32L4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) + !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) hdma->Init.SrcInc = DMA_SINC_INCREMENTED; hdma->Init.DestInc = DMA_DINC_FIXED; #endif @@ -322,7 +322,7 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; #if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32L4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) + !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) hdma->Init.SrcInc = DMA_SINC_FIXED; hdma->Init.DestInc = DMA_DINC_INCREMENTED; #endif @@ -342,7 +342,7 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) return -EIO; } #elif !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32L4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) + !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) if (HAL_DMA_ConfigChannelAttributes(&dev_data->hdma, DMA_CHANNEL_NPRIV) != HAL_OK) { LOG_ERR("HAL_DMA_ConfigChannelAttributes: "); return -EIO; From e846fff8a281c8857641d53cbbaecde4aa0f356d Mon Sep 17 00:00:00 2001 From: Mario Paja Date: Mon, 15 Sep 2025 15:00:19 +0200 Subject: [PATCH 4/4] samples: i2s: output: add nucleo_l552ze_q Add nucleo_l552ze_q board in samples/drivers/i2s/output Signed-off-by: Mario Paja --- .../i2s/output/boards/nucleo_l552ze_q.conf | 1 + .../i2s/output/boards/nucleo_l552ze_q.overlay | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 samples/drivers/i2s/output/boards/nucleo_l552ze_q.conf create mode 100644 samples/drivers/i2s/output/boards/nucleo_l552ze_q.overlay diff --git a/samples/drivers/i2s/output/boards/nucleo_l552ze_q.conf b/samples/drivers/i2s/output/boards/nucleo_l552ze_q.conf new file mode 100644 index 0000000000000..4f3f73a1e06a5 --- /dev/null +++ b/samples/drivers/i2s/output/boards/nucleo_l552ze_q.conf @@ -0,0 +1 @@ +CONFIG_HEAP_MEM_POOL_SIZE=4192 diff --git a/samples/drivers/i2s/output/boards/nucleo_l552ze_q.overlay b/samples/drivers/i2s/output/boards/nucleo_l552ze_q.overlay new file mode 100644 index 0000000000000..26dfeaa298a7b --- /dev/null +++ b/samples/drivers/i2s/output/boards/nucleo_l552ze_q.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Mario Paja + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2s-tx = &sai1_a; + }; +}; + +/* 44.117KHz (0.03% Error) */ +&pllsai1 { + div-m = <1>; + mul-n = <48>; + div-r = <2>; + div-q = <2>; + div-p = <17>; + clocks = <&clk_msi>; + status = "okay"; +}; + +&sai1_a { + pinctrl-0 = <&sai1_mclk_a_pe2 &sai1_sd_a_pe6 + &sai1_fs_a_pe4 &sai1_sck_a_pe5>; + pinctrl-names = "default"; + status = "okay"; + mclk-enable; + mclk-divider = "div-256"; + dma-names = "tx"; +}; + +&dmamux1 { + status = "okay"; +}; + +&dma1 { + status = "okay"; +};