diff --git a/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts b/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts index e190eee2b2513..de46d5301aa32 100644 --- a/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts +++ b/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts @@ -111,16 +111,6 @@ msi-range = <11>; }; -&pll { - clocks = <&clk_msi>; - div-m = <3>; - mul-n = <6>; - div-r = <2>; - div-q = <2>; - div-p = <2>; - status = "okay"; -}; - &rcc { clocks = <&clk_msi>; clock-frequency = ; diff --git a/boards/arm/stm32vl_disco/stm32vl_disco.dts b/boards/arm/stm32vl_disco/stm32vl_disco.dts index b869e362ebc98..ab6127e2cf8c2 100644 --- a/boards/arm/stm32vl_disco/stm32vl_disco.dts +++ b/boards/arm/stm32vl_disco/stm32vl_disco.dts @@ -52,6 +52,7 @@ &pll { mul = <6>; + prediv = <1>; clocks = <&clk_hsi>; status = "okay"; }; diff --git a/drivers/clock_control/clock_stm32_ll_common.c b/drivers/clock_control/clock_stm32_ll_common.c index c83851d8fa186..70e5063ac6661 100644 --- a/drivers/clock_control/clock_stm32_ll_common.c +++ b/drivers/clock_control/clock_stm32_ll_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Linaro Limited. + * Copyright (c) 2017-2022 Linaro Limited. * Copyright (c) 2017 RnDity Sp. z o.o. * * SPDX-License-Identifier: Apache-2.0 @@ -24,10 +24,10 @@ #define fn_apb1_prescaler(v) LL_RCC_APB1_DIV_ ## v #define apb1_prescaler(v) fn_apb1_prescaler(v) -#ifndef CONFIG_SOC_SERIES_STM32F0X +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define fn_apb2_prescaler(v) LL_RCC_APB2_DIV_ ## v #define apb2_prescaler(v) fn_apb2_prescaler(v) -#endif /* CONFIG_SOC_SERIES_STM32F0X */ +#endif #define fn_mco1_prescaler(v) LL_RCC_MCO1_DIV_ ## v #define mco1_prescaler(v) fn_mco1_prescaler(v) @@ -45,14 +45,10 @@ LL_RCC_MSIRANGESEL_RUN, LL_RCC_MSI_GetRange()) #endif -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_SOC_SERIES_STM32WLX) -#define __LL_RCC_CALC_HCLK_FREQ __LL_RCC_CALC_HCLK1_FREQ -#endif - -#if defined(CONFIG_SOC_SERIES_STM32WBX) +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler) #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK4_FREQ #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB4Prescaler -#elif defined(CONFIG_SOC_SERIES_STM32WLX) +#elif DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb3_prescaler) #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK3_FREQ #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB3Prescaler #else @@ -65,32 +61,6 @@ #define STM32WL_DUAL_CORE #endif -/** - * @brief fill in AHB/APB buses configuration structure - */ -static void config_bus_clk_init(LL_UTILS_ClkInitTypeDef *clk_init) -{ -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE) - clk_init->CPU2CLKDivider = ahb_prescaler(STM32_CPU2_PRESCALER); -#endif -#if defined(CONFIG_SOC_SERIES_STM32WBX) - clk_init->CPU1CLKDivider = ahb_prescaler(STM32_CPU1_PRESCALER); - clk_init->AHB4CLKDivider = ahb_prescaler(STM32_AHB4_PRESCALER); -#elif defined(CONFIG_SOC_SERIES_STM32WLX) - clk_init->CPU1CLKDivider = ahb_prescaler(STM32_CPU1_PRESCALER); - clk_init->AHB3CLKDivider = ahb_prescaler(STM32_AHB3_PRESCALER); -#else - clk_init->AHBCLKDivider = ahb_prescaler(STM32_AHB_PRESCALER); -#endif /* CONFIG_SOC_SERIES_STM32WBX */ - - clk_init->APB1CLKDivider = apb1_prescaler(STM32_APB1_PRESCALER); - -#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \ - !defined (CONFIG_SOC_SERIES_STM32G0X) - clk_init->APB2CLKDivider = apb2_prescaler(STM32_APB2_PRESCALER); -#endif -} - static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) { return clock / prescaler; @@ -100,69 +70,15 @@ 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); + volatile uint32_t *reg; + uint32_t reg_val; ARG_UNUSED(dev); - switch (pclken->bus) { - case STM32_CLOCK_BUS_AHB1: - LL_AHB1_GRP1_EnableClock(pclken->enr); - break; -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB2_SUPPORT) || \ - defined(CONFIG_SOC_SERIES_STM32F7X) || \ - defined(CONFIG_SOC_SERIES_STM32F2X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) - case STM32_CLOCK_BUS_AHB2: - LL_AHB2_GRP1_EnableClock(pclken->enr); - break; -#endif /* CONFIG_SOC_SERIES_STM32_* */ -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB3_SUPPORT) || \ - defined(CONFIG_SOC_SERIES_STM32F7X) || \ - defined(CONFIG_SOC_SERIES_STM32F2X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) - case STM32_CLOCK_BUS_AHB3: - LL_AHB3_GRP1_EnableClock(pclken->enr); - break; -#endif /* CONFIG_SOC_SERIES_STM32_* */ - case STM32_CLOCK_BUS_APB1: - LL_APB1_GRP1_EnableClock(pclken->enr); - break; -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F0X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) - case STM32_CLOCK_BUS_APB1_2: - LL_APB1_GRP2_EnableClock(pclken->enr); - break; -#endif /* CONFIG_SOC_SERIES_STM32_* */ -#if !defined(CONFIG_SOC_SERIES_STM32F0X) - case STM32_CLOCK_BUS_APB2: - LL_APB2_GRP1_EnableClock(pclken->enr); - break; -#endif -#if defined(CONFIG_SOC_SERIES_STM32WLX) - case STM32_CLOCK_BUS_APB3: - LL_APB3_GRP1_EnableClock(pclken->enr); - break; -#endif -#if defined (CONFIG_SOC_SERIES_STM32L0X) || \ - defined (CONFIG_SOC_SERIES_STM32G0X) - case STM32_CLOCK_BUS_IOP: - LL_IOP_GRP1_EnableClock(pclken->enr); - break; -#endif - default: - return -ENOTSUP; - } + reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus); + reg_val = *reg; + reg_val |= pclken->enr; + *reg = reg_val; return 0; } @@ -172,70 +88,21 @@ 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); + volatile uint32_t *reg; + uint32_t reg_val; ARG_UNUSED(dev); - switch (pclken->bus) { - case STM32_CLOCK_BUS_AHB1: - LL_AHB1_GRP1_DisableClock(pclken->enr); - break; -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB2_SUPPORT) || \ - defined(CONFIG_SOC_SERIES_STM32F7X) || \ - defined(CONFIG_SOC_SERIES_STM32F2X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) - case STM32_CLOCK_BUS_AHB2: - LL_AHB2_GRP1_DisableClock(pclken->enr); - break; -#endif /* CONFIG_SOC_SERIES_STM32_* */ -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB3_SUPPORT) || \ - defined(CONFIG_SOC_SERIES_STM32F7X) || \ - defined(CONFIG_SOC_SERIES_STM32F2X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) - case STM32_CLOCK_BUS_AHB3: - LL_AHB3_GRP1_DisableClock(pclken->enr); - break; -#endif /* CONFIG_SOC_SERIES_STM32_* */ - case STM32_CLOCK_BUS_APB1: - LL_APB1_GRP1_DisableClock(pclken->enr); - break; -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F0X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) - case STM32_CLOCK_BUS_APB1_2: - LL_APB1_GRP2_DisableClock(pclken->enr); - break; -#endif /* CONFIG_SOC_SERIES_STM32_* */ -#if !defined(CONFIG_SOC_SERIES_STM32F0X) - case STM32_CLOCK_BUS_APB2: - LL_APB2_GRP1_DisableClock(pclken->enr); - break; -#endif -#if defined(CONFIG_SOC_SERIES_STM32WLX) - case STM32_CLOCK_BUS_APB3: - LL_APB3_GRP1_DisableClock(pclken->enr); - break; -#endif -#if defined (CONFIG_SOC_SERIES_STM32L0X) || \ - defined (CONFIG_SOC_SERIES_STM32G0X) - case STM32_CLOCK_BUS_IOP: - LL_IOP_GRP1_DisableClock(pclken->enr); - break; -#endif - default: + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ return -ENOTSUP; } + reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus); + reg_val = *reg; + reg_val &= ~pclken->enr; + *reg = reg_val; + return 0; } @@ -253,57 +120,51 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, */ uint32_t ahb_clock = SystemCoreClock; uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_APB1_PRESCALER); -#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \ - !defined (CONFIG_SOC_SERIES_STM32G0X) +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), apb2_prescaler) uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_APB2_PRESCALER); +#elif defined(STM32_CLOCK_BUS_APB2) + /* APB2 bus exists, but w/o dedicated prescaler */ + uint32_t apb2_clock = apb1_clock; #endif -#if defined(CONFIG_SOC_SERIES_STM32WLX) +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb3_prescaler) uint32_t ahb3_clock = get_bus_clock(ahb_clock * STM32_CPU1_PRESCALER, STM32_AHB3_PRESCALER); +#elif defined(STM32_CLOCK_BUS_AHB3) + /* AHB3 bus exists, but w/o dedicated prescaler */ + uint32_t ahb3_clock = ahb_clock; #endif ARG_UNUSED(clock); switch (pclken->bus) { case STM32_CLOCK_BUS_AHB1: +#if defined(STM32_CLOCK_BUS_AHB2) case STM32_CLOCK_BUS_AHB2: -#if !defined(CONFIG_SOC_SERIES_STM32WLX) - case STM32_CLOCK_BUS_AHB3: #endif -#if defined (CONFIG_SOC_SERIES_STM32L0X) || \ - defined (CONFIG_SOC_SERIES_STM32G0X) +#if defined(STM32_CLOCK_BUS_IOP) case STM32_CLOCK_BUS_IOP: #endif *rate = ahb_clock; break; +#if defined(STM32_CLOCK_BUS_AHB3) + case STM32_CLOCK_BUS_AHB3: + *rate = ahb3_clock; + break; +#endif case STM32_CLOCK_BUS_APB1: -#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32L5X) || \ - defined(CONFIG_SOC_SERIES_STM32F0X) || \ - defined(CONFIG_SOC_SERIES_STM32WBX) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) +#if defined(STM32_CLOCK_BUS_APB1_2) case STM32_CLOCK_BUS_APB1_2: -#endif /* CONFIG_SOC_SERIES_STM32_* */ -#if defined(CONFIG_SOC_SERIES_STM32G0X) - case STM32_CLOCK_BUS_APB2: - /* - * STM32G0x only has one APB, but two reset/clock enable - * registers for peripherals, so return the APB1 clock rate here - */ -#endif /* CONFIG_SOC_SERIES_STM32G0X */ +#endif *rate = apb1_clock; break; -#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \ - !defined (CONFIG_SOC_SERIES_STM32G0X) +#if defined(STM32_CLOCK_BUS_APB2) case STM32_CLOCK_BUS_APB2: *rate = apb2_clock; break; #endif -#if defined(CONFIG_SOC_SERIES_STM32WLX) - case STM32_CLOCK_BUS_AHB3: +#if defined(STM32_CLOCK_BUS_APB3) case STM32_CLOCK_BUS_APB3: - /* AHB3 and APB3 share the same clock and prescaler. */ + /* STM32WL: AHB3 and APB3 share the same clock and prescaler. */ *rate = ahb3_clock; break; #endif @@ -324,7 +185,7 @@ static struct clock_control_driver_api stm32_clock_control_api = { * Unconditionally switch the system clock source to HSI. */ __unused -static void stm32_clock_switch_to_hsi(uint32_t new_ahb_prescaler) +static void stm32_clock_switch_to_hsi(void) { /* Enable HSI if not enabled */ if (LL_RCC_HSI_IsReady() != 1) { @@ -337,7 +198,6 @@ static void stm32_clock_switch_to_hsi(uint32_t new_ahb_prescaler) /* Set HSI as SYSCLCK source */ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); - LL_RCC_SetAHBPrescaler(new_ahb_prescaler); while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { } } @@ -359,196 +219,67 @@ static inline void stm32_clock_control_mco_init(void) #endif /* CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK */ } - -/** - * @brief Initialize clocks for the stm32 - * - * This routine is called to enable and configure the clocks and PLL - * of the soc on the board. It depends on the board definition. - * This function is called on the startup and also to restore the config - * when exiting for low power mode. - * - * @param dev clock device struct - * - * @return 0 - */ -int stm32_clock_control_init(const struct device *dev) +__unused +static int set_up_plls(void) { - LL_UTILS_ClkInitTypeDef s_ClkInitStruct; - uint32_t hclk_prescaler; - uint32_t flash_prescaler; -#if STM32_SYSCLK_SRC_HSE || STM32_SYSCLK_SRC_MSI - uint32_t new_hclk_freq; - uint32_t old_flash_freq; - uint32_t new_flash_freq; -#endif - - ARG_UNUSED(dev); - - /* configure clock for AHB/APB buses */ - config_bus_clk_init((LL_UTILS_ClkInitTypeDef *)&s_ClkInitStruct); - - /* update local hclk and flash-clk prescaler variable */ -#if defined(CONFIG_SOC_SERIES_STM32WBX) - hclk_prescaler = s_ClkInitStruct.CPU1CLKDivider; - flash_prescaler = s_ClkInitStruct.AHB4CLKDivider; -#elif defined(CONFIG_SOC_SERIES_STM32WLX) - hclk_prescaler = s_ClkInitStruct.CPU1CLKDivider; - flash_prescaler = s_ClkInitStruct.AHB3CLKDivider; -#else - hclk_prescaler = s_ClkInitStruct.AHBCLKDivider; - flash_prescaler = hclk_prescaler; -#endif - - /* Some clocks would be activated by default */ - config_enable_default_clocks(); - -#if STM32_SYSCLK_SRC_PLL - LL_UTILS_PLLInitTypeDef s_PLLInitStruct; - - /* configure PLL input settings */ - config_pll_init(&s_PLLInitStruct); +#if defined(STM32_PLL_ENABLED) + int r; /* + * Case of chain-loaded applications: * Switch to HSI and disable the PLL before configuration. * (Switching to HSI makes sure we have a SYSCLK source in * case we're currently running from the PLL we're about to * turn off and reconfigure.) * - * Don't use s_ClkInitStruct.AHBCLKDivider as the AHB - * prescaler here. In this configuration, that's the value to - * use when the SYSCLK source is the PLL, not HSI. */ - stm32_clock_switch_to_hsi(LL_RCC_SYSCLK_DIV_1); + if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + stm32_clock_switch_to_hsi(); + } LL_RCC_PLL_Disable(); #ifdef CONFIG_SOC_SERIES_STM32F7X - /* Assuming we stay on Power Scale default value: Power Scale 1 */ - if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 180000000) { - LL_PWR_EnableOverDriveMode(); - while (LL_PWR_IsActiveFlag_OD() != 1) { - /* Wait for OverDrive mode ready */ - } - LL_PWR_EnableOverDriveSwitching(); - while (LL_PWR_IsActiveFlag_ODSW() != 1) { - /* Wait for OverDrive switch ready */ - } - } + /* Assuming we stay on Power Scale default value: Power Scale 1 */ + if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 180000000) { + LL_PWR_EnableOverDriveMode(); + while (LL_PWR_IsActiveFlag_OD() != 1) { + /* Wait for OverDrive mode ready */ + } + LL_PWR_EnableOverDriveSwitching(); + while (LL_PWR_IsActiveFlag_ODSW() != 1) { + /* Wait for OverDrive switch ready */ + } + } #endif #if STM32_PLL_Q_DIVISOR MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ, STM32_PLL_Q_DIVISOR << RCC_PLLCFGR_PLLQ_Pos); -#endif /* STM32_PLL_Q_DIVISOR */ - -#if STM32_PLL_SRC_MSI - - /* Set MSI Range */ -#if defined(RCC_CR_MSIRGSEL) - LL_RCC_MSI_EnableRangeSelection(); -#endif /* RCC_CR_MSIRGSEL */ - LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_CR_MSIRANGE_Pos); - LL_RCC_MSI_SetCalibTrimming(0); - -#if STM32_MSI_PLL_MODE - -#ifndef STM32_LSE_ENABLED -#error "MSI Hardware auto calibration requires LSE clock activation" #endif - /* Enable MSI hardware auto calibration */ - LL_RCC_MSI_EnablePLLMode(); -#endif - - /* Switch to PLL with MSI as clock source */ - LL_PLL_ConfigSystemClock_MSI(&s_PLLInitStruct, &s_ClkInitStruct); - - /* Disable other clocks */ - LL_RCC_HSI_Disable(); - LL_RCC_HSE_Disable(); - -#elif STM32_PLL_SRC_HSI - /* Switch to PLL with HSI as clock source */ - LL_PLL_ConfigSystemClock_HSI(&s_PLLInitStruct, &s_ClkInitStruct); - /* Disable other clocks */ - LL_RCC_HSE_Disable(); - LL_RCC_MSI_Disable(); - -#elif STM32_PLL_SRC_HSE - -#ifndef CONFIG_SOC_SERIES_STM32WLX - int hse_bypass; - if (IS_ENABLED(STM32_HSE_BYPASS)) { - hse_bypass = LL_UTILS_HSEBYPASS_ON; - } else { - hse_bypass = LL_UTILS_HSEBYPASS_OFF; - } -#else - if (IS_ENABLED(STM32_HSE_TCXO)) { - LL_RCC_HSE_EnableTcxo(); - } - if (IS_ENABLED(STM32_HSE_DIV2)) { - LL_RCC_HSE_EnableDiv2(); + r = config_pll_sysclock(); + if (r < 0) { + return -ENOTSUP; } -#endif - /* Switch to PLL with HSE as clock source */ - LL_PLL_ConfigSystemClock_HSE( -#if !defined(CONFIG_SOC_SERIES_STM32WBX) && !defined(CONFIG_SOC_SERIES_STM32WLX) - CONFIG_CLOCK_STM32_HSE_CLOCK, -#endif -#ifndef CONFIG_SOC_SERIES_STM32WLX - hse_bypass, -#endif - &s_PLLInitStruct, - &s_ClkInitStruct); - - /* Disable other clocks */ - LL_RCC_HSI_Disable(); - LL_RCC_MSI_Disable(); - -#endif /* STM32_PLL_SRC_* */ - -#elif STM32_SYSCLK_SRC_HSE - - old_flash_freq = RCC_CALC_FLASH_FREQ(HAL_RCC_GetSysClockFreq(), - GET_CURRENT_FLASH_PRESCALER()); - - /* Calculate new SystemCoreClock variable based on HSE freq */ - uint32_t hse_freq; - if (IS_ENABLED(STM32_HSE_DIV2)) { - hse_freq = CONFIG_CLOCK_STM32_HSE_CLOCK / 2; - } else { - hse_freq = CONFIG_CLOCK_STM32_HSE_CLOCK; + /* Enable PLL */ + LL_RCC_PLL_Enable(); + while (LL_RCC_PLL_IsReady() != 1U) { + /* Wait for PLL ready */ } - new_hclk_freq = __LL_RCC_CALC_HCLK_FREQ(hse_freq, hclk_prescaler); -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_SOC_SERIES_STM32WLX) - new_flash_freq = RCC_CALC_FLASH_FREQ(CONFIG_CLOCK_STM32_HSE_CLOCK, - flash_prescaler); -#else - new_flash_freq = new_hclk_freq; -#endif +#endif /* STM32_PLL_ENABLED */ -#if defined(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) - __ASSERT(new_hclk_freq == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, - "Config mismatch HCLK frequency %u %u", - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, new_hclk_freq); -#endif + return 0; +} - /* If freq increases, set flash latency before any clock setting */ - if (new_flash_freq > old_flash_freq) { - LL_SetFlashLatency(new_flash_freq); - } +static void set_up_fixed_clock_sources(void) +{ - /* Enable HSE if not enabled */ - if (LL_RCC_HSE_IsReady() != 1) { -#ifdef CONFIG_SOC_SERIES_STM32WLX - if (IS_ENABLED(STM32_HSE_TCXO)) { - LL_RCC_HSE_EnableTcxo(); - } -#elif !defined(CONFIG_SOC_SERIES_STM32WBX) + if (IS_ENABLED(STM32_HSE_ENABLED)) { +#if defined(STM32_HSE_BYPASS) /* Check if need to enable HSE bypass feature or not */ if (IS_ENABLED(STM32_HSE_BYPASS)) { LL_RCC_HSE_EnableBypass(); @@ -556,7 +287,12 @@ int stm32_clock_control_init(const struct device *dev) LL_RCC_HSE_DisableBypass(); } #endif - +#if STM32_HSE_TCXO + LL_RCC_HSE_EnableTcxo(); +#endif +#if STM32_HSE_DIV2 + LL_RCC_HSE_EnableDiv2(); +#endif /* Enable HSE */ LL_RCC_HSE_Enable(); while (LL_RCC_HSE_IsReady() != 1) { @@ -564,158 +300,152 @@ int stm32_clock_control_init(const struct device *dev) } } - /* Set HSE as SYSCLCK source */ - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); - LL_RCC_SetAHBPrescaler(hclk_prescaler); - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { + if (IS_ENABLED(STM32_HSI_ENABLED)) { + /* 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 */ + } + } } - /* Update SystemCoreClock variable */ - LL_SetSystemCoreClock(new_hclk_freq); +#if defined(STM32_MSI_ENABLED) + if (IS_ENABLED(STM32_MSI_ENABLED)) { + /* Set MSI Range */ +#if defined(RCC_CR_MSIRGSEL) + LL_RCC_MSI_EnableRangeSelection(); +#endif /* RCC_CR_MSIRGSEL */ - /* Set APB1 & APB2 prescaler*/ - LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider); -#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \ - !defined (CONFIG_SOC_SERIES_STM32G0X) - LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider); -#endif -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE) - LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct.CPU2CLKDivider); +#if defined(CONFIG_SOC_SERIES_STM32L0X) || defined(CONFIG_SOC_SERIES_STM32L1X) + LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_ICSCR_MSIRANGE_Pos); +#else + LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_CR_MSIRANGE_Pos); +#endif /* CONFIG_SOC_SERIES_STM32L0X || CONFIG_SOC_SERIES_STM32L1X */ + +#if STM32_MSI_PLL_MODE + /* Enable MSI hardware auto calibration */ + LL_RCC_MSI_EnablePLLMode(); #endif -#ifdef CONFIG_SOC_SERIES_STM32WBX - LL_RCC_SetAHB4Prescaler(s_ClkInitStruct.AHB4CLKDivider); -#endif /* CONFIG_SOC_SERIES_STM32WBX */ -#ifdef CONFIG_SOC_SERIES_STM32WLX - LL_RCC_SetAHB3Prescaler(s_ClkInitStruct.AHB3CLKDivider); -#endif /* CONFIG_SOC_SERIES_STM32WLX */ - /* If freq not increased, set flash latency after all clock setting */ - if (new_flash_freq <= old_flash_freq) { - LL_SetFlashLatency(new_flash_freq); + LL_RCC_MSI_SetCalibTrimming(0); + + /* Enable MSI if not enabled */ + if (LL_RCC_MSI_IsReady() != 1) { + /* Enable MSI */ + LL_RCC_MSI_Enable(); + while (LL_RCC_MSI_IsReady() != 1) { + /* Wait for MSI ready */ + } + } } +#endif /* STM32_MSI_ENABLED */ - /* Disable other clocks */ - LL_RCC_HSI_Disable(); - LL_RCC_MSI_Disable(); - LL_RCC_PLL_Disable(); +} -#elif STM32_SYSCLK_SRC_MSI +/** + * @brief Initialize clocks for the stm32 + * + * This routine is called to enable and configure the clocks and PLL + * of the soc on the board. It depends on the board definition. + * This function is called on the startup and also to restore the config + * when exiting for low power mode. + * + * @param dev clock device struct + * + * @return 0 + */ +int stm32_clock_control_init(const struct device *dev) +{ + int r; + + ARG_UNUSED(dev); + + /* Some clocks would be activated by default */ + config_enable_default_clocks(); + +#if defined(FLASH_ACR_LATENCY) + uint32_t old_flash_freq; + uint32_t new_flash_freq; old_flash_freq = RCC_CALC_FLASH_FREQ(HAL_RCC_GetSysClockFreq(), GET_CURRENT_FLASH_PRESCALER()); - new_hclk_freq = __LL_RCC_CALC_HCLK_FREQ( - RCC_CALC_MSI_RUN_FREQ(), - hclk_prescaler); -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_SOC_SERIES_STM32WLX) - new_flash_freq = RCC_CALC_FLASH_FREQ( - RCC_CALC_MSI_RUN_FREQ(), - flash_prescaler); -#else - new_flash_freq = new_hclk_freq; -#endif - -#if defined(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) - __ASSERT(new_hclk_freq == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, - "Config mismatch HCLK frequency %u %u", - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, new_hclk_freq); -#endif + new_flash_freq = RCC_CALC_FLASH_FREQ(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + STM32_FLASH_PRESCALER); /* If freq increases, set flash latency before any clock setting */ - if (new_flash_freq > old_flash_freq) { - LL_SetFlashLatency(new_flash_freq); + if (old_flash_freq < CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { + LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); } +#endif /* FLASH_ACR_LATENCY */ - /* Set MSI Range */ -#if defined(RCC_CR_MSIRGSEL) - LL_RCC_MSI_EnableRangeSelection(); -#endif /* RCC_CR_MSIRGSEL */ - -#if defined(CONFIG_SOC_SERIES_STM32L0X) || defined(CONFIG_SOC_SERIES_STM32L1X) - LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_ICSCR_MSIRANGE_Pos); -#else - LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_CR_MSIRANGE_Pos); -#endif /* CONFIG_SOC_SERIES_STM32L0X || CONFIG_SOC_SERIES_STM32L1X */ + /* Set up indiviual enabled clocks */ + set_up_fixed_clock_sources(); -#if STM32_MSI_PLL_MODE - /* Enable MSI hardware auto calibration */ - LL_RCC_MSI_EnablePLLMode(); -#endif + /* Set up PLLs */ + r = set_up_plls(); + if (r < 0) { + return r; + } - /* Enable MSI if not enabled */ - if (LL_RCC_MSI_IsReady() != 1) { - /* Enable MSI */ - LL_RCC_MSI_Enable(); - while (LL_RCC_MSI_IsReady() != 1) { - /* Wait for HSI ready */ - } + if (DT_PROP(DT_NODELABEL(rcc), undershoot_prevention) && + (STM32_CORE_PRESCALER == LL_RCC_SYSCLK_DIV_1) && + (MHZ(80) < CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)) { + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); + } else { + LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_CORE_PRESCALER)); } +#if STM32_SYSCLK_SRC_PLL + /* Set PLL as System Clock Source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { + } +#elif STM32_SYSCLK_SRC_HSE + /* Set HSE as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { + } +#elif STM32_SYSCLK_SRC_MSI /* Set MSI as SYSCLCK source */ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); - LL_RCC_SetAHBPrescaler(hclk_prescaler); while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) { } +#elif STM32_SYSCLK_SRC_HSI + stm32_clock_switch_to_hsi(); +#endif /* STM32_SYSCLK_SRC_... */ - /* Update SystemCoreClock variable */ - LL_SetSystemCoreClock(new_hclk_freq); + if (DT_PROP(DT_NODELABEL(rcc), undershoot_prevention) && + (STM32_CORE_PRESCALER == LL_RCC_SYSCLK_DIV_1) && + (MHZ(80) < CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)) { + LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_CORE_PRESCALER)); + } - /* Set APB1 & APB2 prescaler*/ - LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider); - LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider); -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE) - LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct.CPU2CLKDivider); -#endif -#ifdef CONFIG_SOC_SERIES_STM32WBX - LL_RCC_SetAHB4Prescaler(s_ClkInitStruct.AHB4CLKDivider); -#endif -#ifdef CONFIG_SOC_SERIES_STM32WLX - LL_RCC_SetAHB3Prescaler(s_ClkInitStruct.AHB3CLKDivider); -#endif +#if defined(FLASH_ACR_LATENCY) /* If freq not increased, set flash latency after all clock setting */ - if (new_flash_freq <= old_flash_freq) { - LL_SetFlashLatency(new_flash_freq); + if (old_flash_freq >= CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { + LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); } +#endif /* FLASH_ACR_LATENCY */ - /* Disable other clocks */ - LL_RCC_HSE_Disable(); - LL_RCC_HSI_Disable(); - LL_RCC_PLL_Disable(); - -#elif STM32_SYSCLK_SRC_HSI - - stm32_clock_switch_to_hsi(hclk_prescaler); + SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; - /* Update SystemCoreClock variable */ - LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK_FREQ(HSI_VALUE, - hclk_prescaler)); - - /* Set APB1 & APB2 prescaler*/ - LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider); -#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \ - !defined (CONFIG_SOC_SERIES_STM32G0X) - LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider); -#endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */ -#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE) - LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct.CPU2CLKDivider); + /* Set bus prescalers prescaler */ + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), apb2_prescaler) + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), cpu2_prescaler) + LL_C2_RCC_SetAHBPrescaler(ahb_prescaler(STM32_CPU2_PRESCALER)); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb3_prescaler) + LL_RCC_SetAHB3Prescaler(ahb_prescaler(STM32_AHB3_PRESCALER)); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler) + LL_RCC_SetAHB4Prescaler(ahb_prescaler(STM32_AHB4_PRESCALER)); #endif -#ifdef CONFIG_SOC_SERIES_STM32WBX - LL_RCC_SetAHB4Prescaler(s_ClkInitStruct.AHB4CLKDivider); -#endif /* CONFIG_SOC_SERIES_STM32WBX */ -#ifdef CONFIG_SOC_SERIES_STM32WLX - LL_RCC_SetAHB3Prescaler(s_ClkInitStruct.AHB3CLKDivider); -#endif /* CONFIG_SOC_SERIES_STM32WLX */ - - /* Set flash latency */ - /* HSI used as SYSCLK, set latency to 0 */ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); - - /* Disable other clocks */ - LL_RCC_HSE_Disable(); - LL_RCC_MSI_Disable(); - LL_RCC_PLL_Disable(); - -#endif /* STM32_SYSCLK_SRC_... */ /* configure MCO1/MCO2 based on Kconfig */ stm32_clock_control_mco_init(); diff --git a/drivers/clock_control/clock_stm32_ll_common.h b/drivers/clock_control/clock_stm32_ll_common.h index 5d7d88a8313b3..7db724c7f748f 100644 --- a/drivers/clock_control/clock_stm32_ll_common.h +++ b/drivers/clock_control/clock_stm32_ll_common.h @@ -32,14 +32,11 @@ #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLLCLK #endif -#if STM32_SYSCLK_SRC_PLL -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit); -#endif /* STM32_SYSCLK_SRC_PLL */ +#ifdef STM32_SYSCLK_SRC_PLL +int config_pll_sysclock(void); +#endif void config_enable_default_clocks(void); -/* Section for functions not available in every Cube packages */ -void LL_RCC_MSI_Disable(void); - /* function exported to the soc power.c */ int stm32_clock_control_init(const struct device *dev); diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index 93cbc401b8404..fff8c698894d0 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -153,14 +153,21 @@ #endif #endif /* CONFIG_CPU_CORTEX_M7 */ +#if defined(CONFIG_CPU_CORTEX_M7) +/* Offset to access bus clock registers from M7 (or only) core */ +#define STM32H7_BUS_CLK_REG DT_REG_ADDR(DT_NODELABEL(rcc)) +#elif defined(CONFIG_CPU_CORTEX_M4) +/* Offset to access bus clock registers from M4 core */ +#define STM32H7_BUS_CLK_REG DT_REG_ADDR(DT_NODELABEL(rcc)) + 0x60 +#endif + static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) { return clock / prescaler; } -#if !defined(CONFIG_CPU_CORTEX_M4) - -static inline uint32_t get_pllout_frequency(uint32_t pllsrc_freq, +__unused +static uint32_t get_pllout_frequency(uint32_t pllsrc_freq, int pllm_div, int plln_mul, int pllout_div) @@ -171,7 +178,8 @@ static inline uint32_t get_pllout_frequency(uint32_t pllsrc_freq, (pllm_div * pllout_div); } -static inline uint32_t get_pllsrc_frequency(void) +__unused +static uint32_t get_pllsrc_frequency(void) { switch (LL_RCC_PLL_GetSource()) { case LL_RCC_PLLSOURCE_HSI: @@ -186,6 +194,7 @@ static inline uint32_t get_pllsrc_frequency(void) } } +__unused static uint32_t get_hclk_frequency(void) { uint32_t sysclk = 0; @@ -214,6 +223,8 @@ static uint32_t get_hclk_frequency(void) return get_bus_clock(sysclk, STM32_HPRE); } +#if !defined(CONFIG_CPU_CORTEX_M4) + static int32_t prepare_regulator_voltage_scale(void) { /* Apply system power supply configuration */ @@ -314,97 +325,52 @@ 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); - int rc = 0; + volatile uint32_t *reg; + uint32_t reg_val; ARG_UNUSED(dev); - /* Both cores can access banks by following LL API */ - /* Using "_Cn_" LL API would restrict access to one or the other */ - z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); - switch (pclken->bus) { - case STM32_CLOCK_BUS_AHB1: - LL_AHB1_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB2: - LL_AHB2_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB3: - LL_AHB3_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB4: - LL_AHB4_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1: - LL_APB1_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1_2: - LL_APB1_GRP2_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB2: - LL_APB2_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB3: - LL_APB3_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB4: - LL_APB4_GRP1_EnableClock(pclken->enr); - break; - default: - rc = -ENOTSUP; - break; + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ + return -ENOTSUP; } + z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); + + reg = (uint32_t *)(STM32H7_BUS_CLK_REG + pclken->bus); + reg_val = *reg; + reg_val |= pclken->enr; + *reg = reg_val; + z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); - return rc; + 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); - int rc = 0; + volatile uint32_t *reg; + uint32_t reg_val; ARG_UNUSED(dev); - /* Both cores can access banks by following LL API */ - /* Using "_Cn_" LL API would restrict access to one or the other */ - z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); - switch (pclken->bus) { - case STM32_CLOCK_BUS_AHB1: - LL_AHB1_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB2: - LL_AHB2_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB3: - LL_AHB3_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB4: - LL_AHB4_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1: - LL_APB1_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1_2: - LL_APB1_GRP2_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB2: - LL_APB2_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB3: - LL_APB3_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB4: - LL_APB4_GRP1_DisableClock(pclken->enr); - break; - default: - rc = -ENOTSUP; - break; + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ + return -ENOTSUP; } + + z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); + + reg = (uint32_t *)(STM32H7_BUS_CLK_REG + pclken->bus); + reg_val = *reg; + reg_val &= ~pclken->enr; + *reg = reg_val; + z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); - return rc; + return 0; } static int stm32_clock_control_get_subsys_rate(const struct device *clock, diff --git a/drivers/clock_control/clock_stm32_ll_u5.c b/drivers/clock_control/clock_stm32_ll_u5.c index b85dc46ee0097..1e999940462a7 100644 --- a/drivers/clock_control/clock_stm32_ll_u5.c +++ b/drivers/clock_control/clock_stm32_ll_u5.c @@ -31,100 +31,65 @@ #define apb3_prescaler(v) z_apb3_prescaler(v) -#ifdef STM32_SYSCLK_SRC_PLL -/** - * @brief fill in pll configuration structure - */ -static void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) { - pllinit->PLLM = STM32_PLL_M_DIVISOR; - pllinit->PLLN = STM32_PLL_N_MULTIPLIER; - pllinit->PLLR = STM32_PLL_R_DIVISOR; + return clock / prescaler; } -#endif /* STM32_SYSCLK_SRC_PLL */ -/** - * @brief Activate default clocks - */ -void config_enable_default_clocks(void) +static uint32_t get_msis_frequency(void) { - /* Enable the power interface clock */ - LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR); - - if (IS_ENABLED(STM32_LSE_ENABLED)) { - if (!LL_PWR_IsEnabledBkUpAccess()) { - /* Enable write access to Backup domain */ - LL_PWR_EnableBkUpAccess(); - while (!LL_PWR_IsEnabledBkUpAccess()) { - /* Wait for Backup domain access */ - } - } - - /* Enable LSE Oscillator */ - LL_RCC_LSE_Enable(); - /* Wait for LSE ready */ - while (!LL_RCC_LSE_IsReady()) { - } + return __LL_RCC_CALC_MSIS_FREQ(LL_RCC_MSIRANGESEL_RUN, + STM32_MSIS_RANGE << RCC_ICSCR1_MSISRANGE_Pos); +} - /* Enable LSESYS additionally */ - LL_RCC_LSE_EnablePropagation(); - /* Wait till LSESYS is ready */ - while (!LL_RCC_LSESYS_IsReady()) { - } +__unused +static uint32_t get_pllsrc_frequency(void) +{ - LL_PWR_DisableBkUpAccess(); + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + return STM32_HSI_FREQ; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + return STM32_HSE_FREQ; + } else if (IS_ENABLED(STM32_PLL_SRC_MSIS)) { + return get_msis_frequency(); } -} -/** - * @brief fill in AHB/APB buses configuration structure - */ -static void config_bus_clk_init(LL_UTILS_ClkInitTypeDef *clk_init) -{ - clk_init->AHBCLKDivider = ahb_prescaler(STM32_AHB_PRESCALER); - clk_init->APB1CLKDivider = apb1_prescaler(STM32_APB1_PRESCALER); - clk_init->APB2CLKDivider = apb2_prescaler(STM32_APB2_PRESCALER); - clk_init->APB3CLKDivider = apb3_prescaler(STM32_APB3_PRESCALER); + __ASSERT(0, "No PLL Source configured"); + return 0; } -static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) +static uint32_t get_startup_frequency(void) { - return clock / prescaler; + switch (LL_RCC_GetSysClkSource()) { + case LL_RCC_SYS_CLKSOURCE_STATUS_MSIS: + return get_msis_frequency(); + case LL_RCC_SYS_CLKSOURCE_STATUS_HSI: + return STM32_HSI_FREQ; + default: + __ASSERT(0, "Unexpected startup freq"); + return 0; + } } 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); + volatile uint32_t *reg; + uint32_t reg_val; ARG_UNUSED(dev); - switch (pclken->bus) { - case STM32_CLOCK_BUS_AHB1: - LL_AHB1_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB2: - LL_AHB2_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB3: - LL_AHB3_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1: - LL_APB1_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1_2: - LL_APB1_GRP2_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB2: - LL_APB2_GRP1_EnableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB3: - LL_APB3_GRP1_EnableClock(pclken->enr); - break; - default: + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ return -ENOTSUP; } + reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus); + reg_val = *reg; + reg_val |= pclken->enr; + *reg = reg_val; + return 0; } @@ -132,35 +97,21 @@ 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); + volatile uint32_t *reg; + uint32_t reg_val; ARG_UNUSED(dev); - switch (pclken->bus) { - case STM32_CLOCK_BUS_AHB1: - LL_AHB1_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB2: - LL_AHB2_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_AHB3: - LL_AHB3_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1: - LL_APB1_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB1_2: - LL_APB1_GRP2_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB2: - LL_APB2_GRP1_DisableClock(pclken->enr); - break; - case STM32_CLOCK_BUS_APB3: - LL_APB3_GRP1_DisableClock(pclken->enr); - break; - default: + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ return -ENOTSUP; } + reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus); + reg_val = *reg; + reg_val &= ~pclken->enr; + *reg = reg_val; + return 0; } @@ -169,6 +120,12 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev, uint32_t *rate) { struct stm32_pclken *pclken = (struct stm32_pclken *)(sys); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + /* * Get AHB Clock (= SystemCoreClock = SYSCLK/prescaler) * SystemCoreClock is preferred to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC @@ -185,6 +142,7 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev, switch (pclken->bus) { case STM32_CLOCK_BUS_AHB1: case STM32_CLOCK_BUS_AHB2: + case STM32_CLOCK_BUS_AHB2_2: case STM32_CLOCK_BUS_AHB3: *rate = ahb_clock; break; @@ -211,6 +169,24 @@ static struct clock_control_driver_api stm32_clock_control_api = { .get_rate = stm32_clock_control_get_subsys_rate, }; +__unused +static int get_vco_input_range(uint32_t m_div, uint32_t *range) +{ + uint32_t vco_freq; + + vco_freq = get_pllsrc_frequency() / m_div; + + if (MHZ(4) <= vco_freq && vco_freq <= MHZ(8)) { + *range = LL_RCC_PLLINPUTRANGE_4_8; + } else if (MHZ(8) < vco_freq && vco_freq <= MHZ(16)) { + *range = LL_RCC_PLLINPUTRANGE_8_16; + } else { + return -ERANGE; + } + + return 0; +} + static void set_regu_voltage(uint32_t hclk_freq) { if (hclk_freq < MHZ(25)) { @@ -226,11 +202,8 @@ static void set_regu_voltage(uint32_t hclk_freq) } } -/* - * Unconditionally switch the system clock source to HSI. - */ __unused -static void clock_switch_to_hsi(uint32_t ahb_prescaler) +static void clock_switch_to_hsi(void) { /* Enable HSI if not enabled */ if (LL_RCC_HSI_IsReady() != 1) { @@ -241,137 +214,91 @@ static void clock_switch_to_hsi(uint32_t ahb_prescaler) } } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Set HSI as SYSCLCK source */ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); - LL_RCC_SetAHBPrescaler(ahb_prescaler); while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { } } -static void set_up_clk_msis(void) -{ -#if defined(STM32_SYSCLK_SRC_MSIS) || defined(STM32_PLL_SRC_MSIS) - /* Set MSIS Range */ - LL_RCC_MSI_EnableRangeSelection(); - - LL_RCC_MSIS_SetRange(STM32_MSIS_RANGE << RCC_ICSCR1_MSISRANGE_Pos); - - if (IS_ENABLED(STM32_MSIS_PLL_MODE)) { - BUILD_ASSERT(STM32_LSE_ENABLED, - "MSI Hardware auto calibration needs LSE clock activation"); - /* Enable MSI hardware auto calibration */ - LL_RCC_MSI_EnablePLLMode(); - } - - /* Set MSIS Range */ - LL_RCC_MSIS_Enable(); - - /* Wait till MSIS is ready */ - while (LL_RCC_MSIS_IsReady() != 1) { - } - -#endif /* STM32_SYSCLK_SRC_MSIS || STM32_PLL_SRC_MSIS */ -} - -/* - * Configure PLL as source of SYSCLK - */ -void config_src_sysclk_pll(LL_UTILS_ClkInitTypeDef s_ClkInitStruct) +__unused +static int set_up_plls(void) { -#ifdef STM32_SYSCLK_SRC_PLL - LL_UTILS_PLLInitTypeDef s_PLLInitStruct; - - /* configure PLL input settings */ - config_pll_init(&s_PLLInitStruct); +#if defined(STM32_PLL_ENABLED) + int r; + uint32_t vco_input_range; /* * Switch to HSI and disable the PLL before configuration. * (Switching to HSI makes sure we have a SYSCLK source in * case we're currently running from the PLL we're about to * turn off and reconfigure.) - * - * Don't use s_ClkInitStruct.AHBCLKDivider as the AHB - * prescaler here. In this configuration, that's the value to - * use when the SYSCLK source is the PLL, not HSI. */ - clock_switch_to_hsi(LL_RCC_SYSCLK_DIV_1); + clock_switch_to_hsi(); + LL_RCC_PLL1_Disable(); - if (IS_ENABLED(STM32_PLL_Q_DIVISOR)) { - LL_RCC_PLL1_SetQ(STM32_PLL_Q_DIVISOR); + /* Configure PLL source */ + /* Can be HSE , HSI MSI */ + if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL_SRC_MSIS)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_MSIS); + } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_HSI); + } else { + return -ENOTSUP; } - set_regu_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); - - if (IS_ENABLED(STM32_PLL_SRC_MSIS)) { - set_up_clk_msis(); - - /* Switch to PLL with MSI as clock source */ - LL_PLL_ConfigSystemClock_MSI(&s_PLLInitStruct, &s_ClkInitStruct); - - /* Disable other clocks */ - LL_RCC_HSI_Disable(); - LL_RCC_HSE_Disable(); - - } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { - /* Switch to PLL with HSI as clock source */ - LL_PLL_ConfigSystemClock_HSI(&s_PLLInitStruct, &s_ClkInitStruct); + r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range); + if (r < 0) { + return r; + } - /* Disable other clocks */ - LL_RCC_HSE_Disable(); - LL_RCC_MSIS_Disable(); + LL_RCC_PLL1_SetDivider(STM32_PLL_M_DIVISOR); - } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { - int hse_bypass; + LL_RCC_PLL1_SetVCOInputRange(vco_input_range); - if (IS_ENABLED(STM32_HSE_BYPASS)) { - hse_bypass = LL_UTILS_HSEBYPASS_ON; - } else { - hse_bypass = LL_UTILS_HSEBYPASS_OFF; - } + LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER); - /* Switch to PLL with HSE as clock source */ - LL_PLL1_ConfigSystemClock_HSE(CONFIG_CLOCK_STM32_HSE_CLOCK, - hse_bypass, - &s_PLLInitStruct, - &s_ClkInitStruct); + LL_RCC_PLL1FRACN_Disable(); - /* Disable other clocks */ - LL_RCC_HSI_Disable(); - LL_RCC_MSIS_Disable(); + if (IS_ENABLED(STM32_PLL_P_ENABLED)) { + LL_RCC_PLL1_SetP(STM32_PLL_P_DIVISOR); + LL_RCC_PLL1_EnableDomain_SAI(); } -#endif /* STM32_SYSCLK_SRC_PLL */ -} - + if (IS_ENABLED(STM32_PLL_Q_ENABLED)) { + LL_RCC_PLL1_SetQ(STM32_PLL_Q_DIVISOR); + LL_RCC_PLL1_EnableDomain_48M(); + } -/* - * Configure HSE as source of SYSCLK - */ -void config_src_sysclk_hse(LL_UTILS_ClkInitTypeDef s_ClkInitStruct) -{ -#ifdef STM32_SYSCLK_SRC_HSE + if (IS_ENABLED(STM32_PLL_R_ENABLED)) { + LL_RCC_PLL1_SetR(STM32_PLL_R_DIVISOR); + LL_RCC_PLL1_EnableDomain_SYS(); + } - uint32_t old_hclk_freq; - uint32_t new_hclk_freq; + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1U) { + } - old_hclk_freq = HAL_RCC_GetHCLKFreq(); +#else + /* Init PLL source to None */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_NONE); - /* Calculate new SystemCoreClock variable based on HSE freq */ - new_hclk_freq = __LL_RCC_CALC_HCLK_FREQ(CONFIG_CLOCK_STM32_HSE_CLOCK, - s_ClkInitStruct.AHBCLKDivider); +#endif /* STM32_PLL_ENABLED */ - __ASSERT(new_hclk_freq == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, - "Config mismatch HCLK frequency %u %u", - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, new_hclk_freq); + return 0; +} - /* If freq increases, set flash latency before any clock setting */ - if (new_hclk_freq > old_hclk_freq) { - LL_SetFlashLatency(new_hclk_freq); - } +static void set_up_fixed_clock_sources(void) +{ - /* Enable HSE if not enabled */ - if (LL_RCC_HSE_IsReady() != 1) { + 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(); @@ -386,149 +313,169 @@ void config_src_sysclk_hse(LL_UTILS_ClkInitTypeDef s_ClkInitStruct) } } - /* Set HSE as SYSCLCK source */ - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); - LL_RCC_SetAHBPrescaler(s_ClkInitStruct.AHBCLKDivider); - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { + if (IS_ENABLED(STM32_HSI_ENABLED)) { + /* 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 */ + } + } } - /* Update SystemCoreClock variable */ - LL_SetSystemCoreClock(new_hclk_freq); - - /* Set peripheral busses prescalers */ - LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider); - LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider); - LL_RCC_SetAPB3Prescaler(s_ClkInitStruct.APB3CLKDivider); + if (IS_ENABLED(STM32_LSE_ENABLED)) { + /* Enable the power interface clock */ + LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR); - /* If freq not increased, set flash latency after all clock setting */ - if (new_hclk_freq <= old_hclk_freq) { - LL_SetFlashLatency(new_hclk_freq); - } + if (!LL_PWR_IsEnabledBkUpAccess()) { + /* Enable write access to Backup domain */ + LL_PWR_EnableBkUpAccess(); + while (!LL_PWR_IsEnabledBkUpAccess()) { + /* Wait for Backup domain access */ + } + } - /* Disable other clocks */ - LL_RCC_HSI_Disable(); - LL_RCC_MSIS_Disable(); - LL_RCC_PLL1_Disable(); + /* Enable LSE Oscillator */ + LL_RCC_LSE_Enable(); + /* Wait for LSE ready */ + while (!LL_RCC_LSE_IsReady()) { + } -#endif /* STM32_SYSCLK_SRC_HSE */ -} + /* Enable LSESYS additionnally */ + LL_RCC_LSE_EnablePropagation(); + /* Wait till LSESYS is ready */ + while (!LL_RCC_LSESYS_IsReady()) { + } -/* - * Configure MSI as source of SYSCLK - */ -void config_src_sysclk_msis(LL_UTILS_ClkInitTypeDef s_ClkInitStruct) -{ -#ifdef STM32_SYSCLK_SRC_MSIS + LL_PWR_DisableBkUpAccess(); + } - uint32_t old_hclk_freq; - uint32_t new_hclk_freq; + if (IS_ENABLED(STM32_MSIS_ENABLED)) { + /* Set MSIS Range */ + LL_RCC_MSI_EnableRangeSelection(); - old_hclk_freq = HAL_RCC_GetHCLKFreq(); + LL_RCC_MSIS_SetRange(STM32_MSIS_RANGE << RCC_ICSCR1_MSISRANGE_Pos); - /* Calculate new SystemCoreClock variable with MSI freq */ - /* MSI freq is defined from RUN range selection */ - new_hclk_freq = __LL_RCC_CALC_HCLK_FREQ( - __LL_RCC_CALC_MSIS_FREQ(LL_RCC_MSIRANGESEL_RUN, - STM32_MSIS_RANGE << RCC_ICSCR1_MSISRANGE_Pos), - s_ClkInitStruct.AHBCLKDivider); + if (IS_ENABLED(STM32_MSIS_PLL_MODE)) { + __ASSERT(STM32_LSE_ENABLED, + "MSIS Hardware auto calibration needs LSE clock activation"); + /* Enable MSI hardware auto calibration */ + LL_RCC_SetMSIPLLMode(LL_RCC_PLLMODE_MSIS); + LL_RCC_MSI_EnablePLLMode(); + } - __ASSERT(new_hclk_freq == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, - "Config mismatch HCLK frequency %u %u", - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, new_hclk_freq); + /* Enable MSIS */ + LL_RCC_MSIS_Enable(); - /* If freq increases, set flash latency before any clock setting */ - if (new_hclk_freq > old_hclk_freq) { - LL_SetFlashLatency(new_hclk_freq); + /* Wait till MSIS is ready */ + while (LL_RCC_MSIS_IsReady() != 1) { + } } - set_regu_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + if (IS_ENABLED(STM32_MSIK_ENABLED)) { + /* Set MSIK Range */ + LL_RCC_MSI_EnableRangeSelection(); - /* Set MSIS as SYSCLCK source */ - set_up_clk_msis(); - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSIS); - LL_RCC_SetAHBPrescaler(s_ClkInitStruct.AHBCLKDivider); - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSIS) { - } + LL_RCC_MSIK_SetRange(STM32_MSIK_RANGE << RCC_ICSCR1_MSIKRANGE_Pos); - /* Update SystemCoreClock variable */ - LL_SetSystemCoreClock(new_hclk_freq); + if (IS_ENABLED(STM32_MSIK_PLL_MODE)) { + __ASSERT(STM32_LSE_ENABLED, + "MSIK Hardware auto calibration needs LSE clock activation"); + /* Enable MSI hardware auto calibration */ + LL_RCC_SetMSIPLLMode(LL_RCC_PLLMODE_MSIK); + LL_RCC_MSI_EnablePLLMode(); + } - /* Set peripheral busses prescalers */ - LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider); - LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider); - LL_RCC_SetAPB3Prescaler(s_ClkInitStruct.APB3CLKDivider); + if (IS_ENABLED(STM32_MSIS_ENABLED)) { + __ASSERT((STM32_MSIK_PLL_MODE == STM32_MSIS_PLL_MODE), + "Please check MSIS/MSIK config consistency"); + } - /* If freq not increased, set flash latency after all clock setting */ - if (new_hclk_freq <= old_hclk_freq) { - LL_SetFlashLatency(new_hclk_freq); + /* Enable MSIK */ + LL_RCC_MSIK_Enable(); + + /* Wait till MSIK is ready */ + while (LL_RCC_MSIK_IsReady() != 1) { + } } - /* Disable other clocks */ - LL_RCC_HSE_Disable(); - LL_RCC_HSI_Disable(); - LL_RCC_PLL1_Disable(); + if (IS_ENABLED(STM32_LSI_ENABLED)) { + /* Enable LSI oscillator */ + LL_RCC_LSI_Enable(); + while (LL_RCC_LSI_IsReady() != 1) { + } + } -#endif /* STM32_SYSCLK_SRC_MSIS */ } -/* - * Configure HSI as source of SYSCLK - */ -void config_src_sysclk_hsi(LL_UTILS_ClkInitTypeDef s_ClkInitStruct) +int stm32_clock_control_init(const struct device *dev) { -#ifdef STM32_SYSCLK_SRC_HSI + uint32_t old_hclk_freq = 0; + int r = 0; - clock_switch_to_hsi(s_ClkInitStruct.AHBCLKDivider); - - /* Update SystemCoreClock variable */ - LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK_FREQ(HSI_VALUE, - s_ClkInitStruct.AHBCLKDivider)); + ARG_UNUSED(dev); - /* Set peripheral busses prescalers */ - LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider); - LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider); - LL_RCC_SetAPB3Prescaler(s_ClkInitStruct.APB3CLKDivider); + /* Current hclk value */ + old_hclk_freq = __LL_RCC_CALC_HCLK_FREQ(get_startup_frequency(), LL_RCC_GetAHBPrescaler()); - /* Set flash latency */ - /* HSI used as SYSCLK, set latency to 0 */ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + /* Set up indiviual enabled clocks */ + set_up_fixed_clock_sources(); - /* Disable other clocks */ - LL_RCC_HSE_Disable(); - LL_RCC_MSIS_Disable(); - LL_RCC_PLL1_Disable(); - -#endif /* STM32_SYSCLK_SRC_HSI */ -} - -int stm32_clock_control_init(const struct device *dev) -{ - LL_UTILS_ClkInitTypeDef s_ClkInitStruct; + /* Set up PLLs */ + r = set_up_plls(); + if (r < 0) { + return r; + } - ARG_UNUSED(dev); + /* Set voltage regulator to comply with targeted system frequency */ + set_regu_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); - /* configure clock for AHB/APB buses */ - config_bus_clk_init((LL_UTILS_ClkInitTypeDef *)&s_ClkInitStruct); + /* Set flash latency */ + /* If freq increases, set flash latency before any clock setting */ + if (old_hclk_freq < CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { + LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + } - /* Some clocks would be activated by default */ - config_enable_default_clocks(); + /* Set peripheral busses 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_SetAPB3Prescaler(apb3_prescaler(STM32_APB3_PRESCALER)); if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { - /* Configure PLL as source of SYSCLK */ - config_src_sysclk_pll(s_ClkInitStruct); + /* Set PLL1 as System Clock Source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { + } } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSE)) { - /* Configure HSE as source of SYSCLK */ - config_src_sysclk_hse(s_ClkInitStruct); + /* Set HSE as SYSCLCK source */ + 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_MSIS)) { - /* Configure MSIS as source of SYSCLK */ - config_src_sysclk_msis(s_ClkInitStruct); + /* Set MSIS as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSIS); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSIS) { + } } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSI)) { - /* Configure HSI as source of SYSCLK */ - config_src_sysclk_hsi(s_ClkInitStruct); + /* Set HSI as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { + } } else { return -ENOTSUP; } + /* Set FLASH latency */ + /* If freq not increased, set flash latency after all clock setting */ + if (old_hclk_freq >= CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { + LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + } + + /* Update CMSIS variable */ + SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + return 0; } diff --git a/drivers/clock_control/clock_stm32f0_f3.c b/drivers/clock_control/clock_stm32f0_f3.c index 956cf7490de7e..235e59d706d4b 100644 --- a/drivers/clock_control/clock_stm32f0_f3.c +++ b/drivers/clock_control/clock_stm32f0_f3.c @@ -19,10 +19,12 @@ #if STM32_SYSCLK_SRC_PLL /** - * @brief fill in pll configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { + uint32_t pll_source, pll_mul, pll_div; + /* * PLL MUL * 2 -> LL_RCC_PLL_MUL_2 -> 0x00000000 @@ -31,8 +33,7 @@ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) * ... * 16 -> LL_RCC_PLL_MUL_16 -> 0x00380000 */ - pllinit->PLLMul = ((STM32_PLL_MULTIPLIER - 2) - << RCC_CFGR_PLLMUL_Pos); + pll_mul = ((STM32_PLL_MULTIPLIER - 2) << RCC_CFGR_PLLMUL_Pos); /* * PLL PREDIV @@ -42,6 +43,8 @@ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) * ... * 16 -> LL_RCC_PREDIV_DIV_16 -> 0x0000000F */ + pll_div = STM32_PLL_PREDIV - 1; + #if defined(RCC_PLLSRC_PREDIV1_SUPPORT) /* * PREDIV1 support is a specific RCC configuration present on @@ -49,10 +52,31 @@ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) * STM32F030xC, STM32F302xE, STM32F303xE and STM32F39xx * cf Reference manual for more details */ - pllinit->PLLDiv = STM32_PLL_PREDIV - 1; + + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE; + } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_mul, pll_div); #else - pllinit->Prediv = STM32_PLL_PREDIV - 1; + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE | pll_div; + } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI_DIV_2; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_mul); #endif /* RCC_PLLSRC_PREDIV1_SUPPORT */ + + return 0; } #endif /* STM32_SYSCLK_SRC_PLL */ @@ -76,11 +100,3 @@ void config_enable_default_clocks(void) #endif #endif /* !CONFIG_SOC_SERIES_STM32F3X */ } - -/** - * @brief Function kept for driver genericity - */ -void LL_RCC_MSI_Disable(void) -{ - /* Do nothing */ -} diff --git a/drivers/clock_control/clock_stm32f1.c b/drivers/clock_control/clock_stm32f1.c index af789aba6017f..cf3b14c66cff6 100644 --- a/drivers/clock_control/clock_stm32f1.c +++ b/drivers/clock_control/clock_stm32f1.c @@ -17,24 +17,19 @@ #if STM32_SYSCLK_SRC_PLL - /* * Select PLL source for STM32F1 Connectivity line devices (STM32F105xx and * STM32F107xx). * Both flags are defined in STM32Cube LL API. Keep only the selected one. */ -#if STM32_PLL_SRC_PLL2 -#undef RCC_PREDIV1_SOURCE_HSE -#else -#undef RCC_PREDIV1_SOURCE_PLL2 -#endif /* STM32_PLL_SRC_PLL2 */ - /** - * @brief fill in pll configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { + uint32_t pll_source, pll_mul, pll_div; + /* * PLLMUL on SOC_STM32F10X_DENSITY_DEVICE * 2 -> LL_RCC_PLL_MUL_2 -> 0x00000000 @@ -49,46 +44,57 @@ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) * 9 -> LL_RCC_PLL_MUL_9 -> 0x001C0000 * 13 -> LL_RCC_PLL_MUL_6_5 -> 0x00340000 */ - pllinit->PLLMul = ((STM32_PLL_MULTIPLIER - 2) - << RCC_CFGR_PLLMULL_Pos); + pll_mul = ((STM32_PLL_MULTIPLIER - 2) << RCC_CFGR_PLLMULL_Pos); -#if STM32_PLL_SRC_HSI - /* In case PLL source is HSI, prediv is 2 */ - pllinit->Prediv = LL_RCC_PREDIV_DIV_2; -#else - /* In case PLL source is not HSI, set prediv case by case */ + if (!IS_ENABLED(STM32_PLL_SRC_HSI)) { + /* In case PLL source is not HSI, set prediv case by case */ #ifdef CONFIG_SOC_STM32F10X_DENSITY_DEVICE - /* PLL prediv */ -#if STM32_PLL_XTPRE - /* - * SOC_STM32F10X_DENSITY_DEVICE: - * PLLXPTRE (depends on PLL source HSE) - * HSE/2 used as PLL source - */ - pllinit->Prediv = LL_RCC_PREDIV_DIV_2; + /* PLL prediv */ + if (IS_ENABLED(STM32_PLL_XTPRE)) { + /* + * SOC_STM32F10X_DENSITY_DEVICE: + * PLLXPTRE (depends on PLL source HSE) + * HSE/2 used as PLL source + */ + pll_div = LL_RCC_PREDIV_DIV_2; + } else { + /* + * SOC_STM32F10X_DENSITY_DEVICE: + * PLLXPTRE (depends on PLL source HSE) + * HSE used as direct PLL source + */ + pll_div = LL_RCC_PREDIV_DIV_1; + } #else - /* - * SOC_STM32F10X_DENSITY_DEVICE: - * PLLXPTRE (depends on PLL source HSE) - * HSE used as direct PLL source - */ - pllinit->Prediv = LL_RCC_PREDIV_DIV_1; -#endif /* STM32_PLL_XTPRE */ -#else - /* - * SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE - * 1 -> LL_RCC_PREDIV_DIV_1 -> 0x00000000 - * 2 -> LL_RCC_PREDIV_DIV_2 -> 0x00000001 - * 3 -> LL_RCC_PREDIV_DIV_3 -> 0x00000002 - * ... - * 16 -> LL_RCC_PREDIV_DIV_16 -> 0x0000000F - */ - pllinit->Prediv = STM32_PLL_PREDIV - 1; + /* + * SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE + * 1 -> LL_RCC_PREDIV_DIV_1 -> 0x00000000 + * 2 -> LL_RCC_PREDIV_DIV_2 -> 0x00000001 + * 3 -> LL_RCC_PREDIV_DIV_3 -> 0x00000002 + * ... + * 16 -> LL_RCC_PREDIV_DIV_16 -> 0x0000000F + */ + pll_div = STM32_PLL_PREDIV - 1; #endif /* CONFIG_SOC_STM32F10X_DENSITY_DEVICE */ + } -#endif /* STM32_PLL_SRC_HSI */ -} + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI_DIV_2; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE | pll_div; +#if defined(RCC_CFGR2_PREDIV1SRC) + } else if (IS_ENABLED(STM32_PLL_SRC_PLL2)) { + pll_source = LL_RCC_PLLSOURCE_PLL2 | pll_div; +#endif + } else { + return -ENOTSUP; + } + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_mul); + + return 0; +} #endif /* STM32_SYSCLK_SRC_PLL */ /** @@ -98,11 +104,3 @@ void config_enable_default_clocks(void) { /* Nothing for now */ } - -/** - * @brief Function kept for driver genericity - */ -void LL_RCC_MSI_Disable(void) -{ - /* Do nothing */ -} diff --git a/drivers/clock_control/clock_stm32f2_f4_f7.c b/drivers/clock_control/clock_stm32f2_f4_f7.c index 5e1c9a87cdee1..e0b75bdea5cb8 100644 --- a/drivers/clock_control/clock_stm32f2_f4_f7.c +++ b/drivers/clock_control/clock_stm32f2_f4_f7.c @@ -26,13 +26,28 @@ #define pllp(v) z_pllp(v) /** - * @brief fill in pll configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { - pllinit->PLLM = pllm(STM32_PLL_M_DIVISOR); - pllinit->PLLN = STM32_PLL_N_MULTIPLIER; - pllinit->PLLP = pllp(STM32_PLL_P_DIVISOR); + uint32_t pll_source, pll_m, pll_n, pll_p; + + pll_n = STM32_PLL_N_MULTIPLIER; + pll_m = pllm(STM32_PLL_M_DIVISOR); + pll_p = pllp(STM32_PLL_P_DIVISOR); + + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_m, pll_n, pll_p); + + return 0; } #endif /* STM32_SYSCLK_SRC_PLL */ @@ -44,11 +59,3 @@ void config_enable_default_clocks(void) /* Power Interface clock enabled by default */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); } - -/** - * @brief Function kept for driver genericity - */ -void LL_RCC_MSI_Disable(void) -{ - /* Do nothing */ -} diff --git a/drivers/clock_control/clock_stm32g0.c b/drivers/clock_control/clock_stm32g0.c index 464cd59824357..e4353a5d653e8 100644 --- a/drivers/clock_control/clock_stm32g0.c +++ b/drivers/clock_control/clock_stm32g0.c @@ -27,13 +27,30 @@ #define pllr(v) z_pllr(v) /** - * @brief Fill PLL configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { - pllinit->PLLN = STM32_PLL_N_MULTIPLIER; - pllinit->PLLM = pll_div(STM32_PLL_M_DIVISOR); - pllinit->PLLR = pllr(STM32_PLL_R_DIVISOR); + uint32_t pll_source, pll_m, pll_n, pll_r; + + pll_n = STM32_PLL_N_MULTIPLIER; + pll_m = pll_div(STM32_PLL_M_DIVISOR); + pll_r = pllr(STM32_PLL_R_DIVISOR); + + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_m, pll_n, pll_r); + + LL_RCC_PLL_EnableDomain_SYS(); + + return 0; } #endif /* STM32_SYSCLK_SRC_PLL */ @@ -45,11 +62,3 @@ void config_enable_default_clocks(void) /* Enable the power interface clock */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); } - -/** - * @brief Function kept for driver genericity - */ -void LL_RCC_MSI_Disable(void) -{ - /* Do nothing */ -} diff --git a/drivers/clock_control/clock_stm32g4.c b/drivers/clock_control/clock_stm32g4.c index c392abbee517b..f7161fb2b7ab3 100644 --- a/drivers/clock_control/clock_stm32g4.c +++ b/drivers/clock_control/clock_stm32g4.c @@ -26,18 +26,35 @@ #define pllr(v) z_pllr(v) /** - * @brief fill in pll configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { - pllinit->PLLM = pllm(STM32_PLL_M_DIVISOR); - pllinit->PLLN = STM32_PLL_N_MULTIPLIER; - pllinit->PLLR = pllr(STM32_PLL_R_DIVISOR); + uint32_t pll_source, pll_m, pll_n, pll_r; /* set power boost mode for sys clock greater than 150MHz */ if (sys_clock_hw_cycles_per_sec() >= MHZ(150)) { LL_PWR_EnableRange1BoostMode(); } + + pll_n = STM32_PLL_N_MULTIPLIER; + pll_m = pllm(STM32_PLL_M_DIVISOR); + pll_r = pllr(STM32_PLL_R_DIVISOR); + + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_m, pll_n, pll_r); + + LL_RCC_PLL_EnableDomain_SYS(); + + return 0; } #endif /* STM32_SYSCLK_SRC_PLL */ @@ -67,11 +84,3 @@ void config_enable_default_clocks(void) LL_PWR_DisableBkUpAccess(); #endif } - -/** - * @brief Function kept for driver genericity - */ -void LL_RCC_MSI_Disable(void) -{ - /* Do nothing */ -} diff --git a/drivers/clock_control/clock_stm32l0_l1.c b/drivers/clock_control/clock_stm32l0_l1.c index 79b6579929813..37545f5b94f0d 100644 --- a/drivers/clock_control/clock_stm32l0_l1.c +++ b/drivers/clock_control/clock_stm32l0_l1.c @@ -26,12 +26,27 @@ #define pll_div(v) z_pll_div(v) /** - * @brief Fill PLL configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { - pllinit->PLLMul = pll_mul(STM32_PLL_MULTIPLIER); - pllinit->PLLDiv = pll_div(STM32_PLL_DIVISOR); + uint32_t pll_source, pll_mul, pll_div; + + pll_mul = pll_mul(STM32_PLL_MULTIPLIER); + pll_div = pll_div(STM32_PLL_DIVISOR); + + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_mul, pll_div); + + return 0; } #endif /* STM32_SYSCLK_SRC_PLL */ diff --git a/drivers/clock_control/clock_stm32l4_l5_wb_wl.c b/drivers/clock_control/clock_stm32l4_l5_wb_wl.c index 07aed0c0afb25..b7e40add29dd4 100644 --- a/drivers/clock_control/clock_stm32l4_l5_wb_wl.c +++ b/drivers/clock_control/clock_stm32l4_l5_wb_wl.c @@ -27,19 +27,39 @@ #define pllr(v) z_pllr(v) /** - * @brief fill in pll configuration structure + * @brief Set up pll configuration */ -void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +int config_pll_sysclock(void) { - pllinit->PLLM = pllm(STM32_PLL_M_DIVISOR); - pllinit->PLLN = STM32_PLL_N_MULTIPLIER; - pllinit->PLLR = pllr(STM32_PLL_R_DIVISOR); + uint32_t pll_source, pll_m, pll_n, pll_r; + #ifdef PWR_CR5_R1MODE /* set power boost mode for sys clock greater than 80MHz */ if (sys_clock_hw_cycles_per_sec() >= MHZ(80)) { LL_PWR_EnableRange1BoostMode(); } #endif /* PWR_CR5_R1MODE */ + + pll_n = STM32_PLL_N_MULTIPLIER; + pll_m = pllm(STM32_PLL_M_DIVISOR); + pll_r = pllr(STM32_PLL_R_DIVISOR); + + /* Configure PLL source */ + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + pll_source = LL_RCC_PLLSOURCE_HSI; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + pll_source = LL_RCC_PLLSOURCE_HSE; + } else if (IS_ENABLED(STM32_PLL_SRC_MSI)) { + pll_source = LL_RCC_PLLSOURCE_MSI; + } else { + return -ENOTSUP; + } + + LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_m, pll_n, pll_r); + + LL_RCC_PLL_EnableDomain_SYS(); + + return 0; } #endif /* STM32_SYSCLK_SRC_PLL */ diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index fd4ab8a59f47d..c451144fc7fbf 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include @@ -157,7 +157,7 @@ usart1: serial@40013800 { compatible = "st,stm32-usart", "st,stm32-uart"; reg = <0x40013800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00004000>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00004000>; interrupts = <27 0>; status = "disabled"; label = "UART_1"; @@ -203,7 +203,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x40013000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00001000>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>; interrupts = <25 3>; status = "disabled"; label = "SPI_1"; @@ -237,7 +237,7 @@ timers1: timers@40012c00 { compatible = "st,stm32-timers"; reg = <0x40012c00 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000800>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000800>; interrupts = <13 0>, <14 0>; interrupt-names = "brk_up_trg_com", "cc"; st,prescaler = <0>; @@ -313,7 +313,7 @@ timers15: timers@40014000 { compatible = "st,stm32-timers"; reg = <0x40014000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00010000>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00010000>; interrupts = <20 0>; interrupt-names = "global"; st,prescaler = <0>; @@ -331,7 +331,7 @@ timers16: timers@40014400 { compatible = "st,stm32-timers"; reg = <0x40014400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00020000>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00020000>; interrupts = <21 0>; interrupt-names = "global"; st,prescaler = <0>; @@ -349,7 +349,7 @@ timers17: timers@40014800 { compatible = "st,stm32-timers"; reg = <0x40014800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00040000>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00040000>; interrupts = <22 0>; interrupt-names = "global"; st,prescaler = <0>; @@ -367,7 +367,7 @@ adc1: adc@40012400 { compatible = "st,stm32-adc"; reg = <0x40012400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000200>; interrupts = <12 0>; status = "disabled"; label = "ADC_1"; diff --git a/dts/arm/st/f0/stm32f030Xc.dtsi b/dts/arm/st/f0/stm32f030Xc.dtsi index f9aef0d0581cd..e202d80ed113c 100644 --- a/dts/arm/st/f0/stm32f030Xc.dtsi +++ b/dts/arm/st/f0/stm32f030Xc.dtsi @@ -66,7 +66,7 @@ usart6: serial@40011400 { compatible = "st,stm32-usart", "st,stm32-uart"; reg = <0x40011400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000020>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000020>; interrupts = <29 0>; status = "disabled"; label = "UART_6"; diff --git a/dts/arm/st/f1/stm32f1.dtsi b/dts/arm/st/f1/stm32f1.dtsi index b127100c32c5e..d460ed0ca7cc4 100644 --- a/dts/arm/st/f1/stm32f1.dtsi +++ b/dts/arm/st/f1/stm32f1.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/f2/stm32f2.dtsi b/dts/arm/st/f2/stm32f2.dtsi index 1917dc21911dc..b5fcbe2a2cc58 100644 --- a/dts/arm/st/f2/stm32f2.dtsi +++ b/dts/arm/st/f2/stm32f2.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index 8fb17cdc46acb..6cf02b2e657c3 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/f4/stm32f4.dtsi b/dts/arm/st/f4/stm32f4.dtsi index 25285cf284b69..f689d595a43ee 100644 --- a/dts/arm/st/f4/stm32f4.dtsi +++ b/dts/arm/st/f4/stm32f4.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index e69f6ecf6605e..06368a3667c50 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index b9c27447c2dad..786a52a2a2e88 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 932339c3a83d5..d78d4ca8ae133 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include @@ -139,6 +139,7 @@ compatible = "st,stm32-rcc"; #clock-cells = <2>; reg = <0x40021000 0x400>; + undershoot-prevention; }; exti: interrupt-controller@40010400 { diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 36a44d2b94313..fbd01853c003b 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -7,7 +7,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index d40e9f5ee2bb8..31d3e39602893 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/l1/stm32l1.dtsi b/dts/arm/st/l1/stm32l1.dtsi index 551bbfccc7ba7..735ca3a34c8a5 100644 --- a/dts/arm/st/l1/stm32l1.dtsi +++ b/dts/arm/st/l1/stm32l1.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index 46c17af8eeccc..419779d50ce59 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include diff --git a/dts/arm/st/l4/stm32l4r5.dtsi b/dts/arm/st/l4/stm32l4r5.dtsi index 3af9e4dc55ec8..6a23bcc3ae6e4 100644 --- a/dts/arm/st/l4/stm32l4r5.dtsi +++ b/dts/arm/st/l4/stm32l4r5.dtsi @@ -19,6 +19,10 @@ }; }; + rcc: rcc@40021000 { + undershoot-prevention; + }; + pinctrl: pin-controller@48000000 { gpiod: gpio@48000c00 { compatible = "st,stm32-gpio"; diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index 15b717a8c97bb..89e434cca6f76 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include @@ -115,6 +115,7 @@ clocks-controller; #clock-cells = <2>; reg = <0x40021000 0x400>; + undershoot-prevention; }; exti: interrupt-controller@4000f400 { diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index bad3291745c67..42289cbacf55b 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index 22c09b1d6327f..d42ccf2430397 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 341bf5a79a603..ff254d9d26d3f 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/dts/bindings/clock/st,stm32-rcc.yaml b/dts/bindings/clock/st,stm32-rcc.yaml index cc4319d775053..1658dd471a4a4 100644 --- a/dts/bindings/clock/st,stm32-rcc.yaml +++ b/dts/bindings/clock/st,stm32-rcc.yaml @@ -10,15 +10,16 @@ description: | System clock source should be selected amongst the clock nodes available in "clocks" node (typically 'clk_hse, clk_hsi', '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 + Core clock frequency should also be defined, using "clock-frequency" property. + Note: + Core clock frequency = SYSCLK / AHB prescaler + Last, peripheral bus clocks (typically PCLK1, PCLK2) should be configured using matching prescaler properties. Here is an example of correctly configured rcc node: &rcc { - clocks = <&pll>; /* Set pll as SYSCLK source */ - clock-frequency = ; /* SYSCLK runs at 80MHz */ - ahb-prescaler = <1>; + clocks = <&pll>; /* Select 80MHz pll as SYSCLK source */ + ahb-prescaler = <2>; + clock-frequency = ; /* = SYSCLK / AHB prescaler */ apb1-presacler = <1>; apb2-presacler = <1>; } @@ -67,8 +68,8 @@ properties: - 256 - 512 description: | - AHB prescaler. Sets a HCLK frequency (feeding Cortex-M Systick) - lower than SYSCLK frequency (actual core frequency). + AHB prescaler. Defines actual core clock frequency (HCLK) + based on system frequency input. The HCLK clocks CPU, AHB, memories and DMA. apb1-prescaler: @@ -91,6 +92,16 @@ properties: - 8 - 16 + undershoot-prevention: + type: boolean + required: false + description: | + On some parts, it could be required to set up highest core frequencies + (>80MHz) in two steps in order to prevent undershoot. + This is done by applying an intermediate AHB prescaler before switching + System Clock source to PLL. Once done, prescaler is set back to expected + value. + clock-cells: - bus - bits diff --git a/dts/bindings/clock/st,stm32f105-pll-clock.yaml b/dts/bindings/clock/st,stm32f105-pll-clock.yaml index b65ea38670dc6..d4b76e6937609 100644 --- a/dts/bindings/clock/st,stm32f105-pll-clock.yaml +++ b/dts/bindings/clock/st,stm32f105-pll-clock.yaml @@ -49,7 +49,7 @@ properties: prediv: type: int - required: false + required: true description: | Configurable prescaler Valid range: 1 - 16 diff --git a/dts/bindings/clock/st,stm32l0-msi-clock.yaml b/dts/bindings/clock/st,stm32l0-msi-clock.yaml index bbbd7dc9fafbf..0d765bc9e902b 100644 --- a/dts/bindings/clock/st,stm32l0-msi-clock.yaml +++ b/dts/bindings/clock/st,stm32l0-msi-clock.yaml @@ -17,10 +17,11 @@ properties: default: 5 description: | MSI clock ranges - 0: range 0 around 65.536 kHz - 1: range 1 around 131.072 kHz - 2: range 2 around 262.144 kHz - 3: range 3 around 524.288 kHz - 4: range 4 around 1.048 MHz - 5: range 5 around 2.097 MHz (reset value) - 6: range 6 around 4.194 MHz + enum: + - 0 # range 0, around 65.536 kHz + - 1 # range 1, around 131.072 kHz + - 2 # range 2, around 262.144 kHz + - 3 # range 3, around 524.288 kHz + - 4 # range 4, around 1.048 MHz + - 5 # range 5, around 2.097 MHz (reset value) + - 6 # range 6, around 4.194 MHz diff --git a/dts/bindings/clock/st,stm32mp1-rcc.yaml b/dts/bindings/clock/st,stm32mp1-rcc.yaml index 39f51f02f15e8..8282b46d11247 100644 --- a/dts/bindings/clock/st,stm32mp1-rcc.yaml +++ b/dts/bindings/clock/st,stm32mp1-rcc.yaml @@ -15,3 +15,4 @@ include: - ahb-prescaler - apb1-prescaler - apb2-prescaler + - undershoot-prevention diff --git a/dts/bindings/clock/st,stm32u5-rcc.yaml b/dts/bindings/clock/st,stm32u5-rcc.yaml index cea21ffef9b4f..5aa4783b910ea 100644 --- a/dts/bindings/clock/st,stm32u5-rcc.yaml +++ b/dts/bindings/clock/st,stm32u5-rcc.yaml @@ -7,7 +7,10 @@ description: | compatible: "st,stm32u5-rcc" -include: st,stm32-rcc.yaml +include: + - name: st,stm32-rcc.yaml + property-blocklist: + - undershoot-prevention properties: diff --git a/dts/bindings/clock/st,stm32wb-rcc.yaml b/dts/bindings/clock/st,stm32wb-rcc.yaml index dce60755fd354..849ef945e3b6f 100644 --- a/dts/bindings/clock/st,stm32wb-rcc.yaml +++ b/dts/bindings/clock/st,stm32wb-rcc.yaml @@ -32,8 +32,8 @@ properties: - 256 - 512 description: | - CPU1 prescaler. Sets a HCLK1 frequency (feeding Cortex-M Systick) - lower than SYSCLK frequency (actual core frequency). + CPU1 prescaler. Sets a HCLK1 frequency (Core frequency) + lower than SYSCLK frequency. The HCLK1 clocks CPU1, AHB1, AHB2, AHB3 and SRAM1. cpu2-prescaler: diff --git a/include/dt-bindings/clock/stm32f1_clock.h b/include/dt-bindings/clock/stm32f1_clock.h new file mode 100644 index 0000000000000..57348652c9ba9 --- /dev/null +++ b/include/dt-bindings/clock/stm32f1_clock.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32F1_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32F1_CLOCK_H_ + +/** Peripheral clock sources */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x014 +#define STM32_CLOCK_BUS_APB2 0x018 +#define STM32_CLOCK_BUS_APB1 0x01c + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB1 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32F1_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32f4_clock.h b/include/dt-bindings/clock/stm32f4_clock.h new file mode 100644 index 0000000000000..38d1a6ab413a6 --- /dev/null +++ b/include/dt-bindings/clock/stm32f4_clock.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32F4_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32F4_CLOCK_H_ + +/** Peripheral clock sources */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x030 +#define STM32_CLOCK_BUS_AHB2 0x034 +#define STM32_CLOCK_BUS_AHB3 0x038 +#define STM32_CLOCK_BUS_APB1 0x040 +#define STM32_CLOCK_BUS_APB2 0x044 +#define STM32_CLOCK_BUS_APB3 0x0A8 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32F4_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32g0_clock.h b/include/dt-bindings/clock/stm32g0_clock.h new file mode 100644 index 0000000000000..246f5eaaa173a --- /dev/null +++ b/include/dt-bindings/clock/stm32g0_clock.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32G0_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32G0_CLOCK_H_ + +/** Peripheral clock sources */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_IOP 0x034 +#define STM32_CLOCK_BUS_AHB1 0x038 +#define STM32_CLOCK_BUS_APB2 0x03c +#define STM32_CLOCK_BUS_APB1 0x040 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_IOP +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB1 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32G0_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32h7_clock.h b/include/dt-bindings/clock/stm32h7_clock.h new file mode 100644 index 0000000000000..608bc2182814f --- /dev/null +++ b/include/dt-bindings/clock/stm32h7_clock.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7_CLOCK_H_ + +/* clock bus references */ +#define STM32_CLOCK_BUS_AHB3 0x134 +#define STM32_CLOCK_BUS_AHB1 0x138 +#define STM32_CLOCK_BUS_AHB2 0x13c +#define STM32_CLOCK_BUS_AHB4 0x140 +#define STM32_CLOCK_BUS_APB3 0x144 +#define STM32_CLOCK_BUS_APB1 0x148 +#define STM32_CLOCK_BUS_APB1_2 0x14c +#define STM32_CLOCK_BUS_APB2 0x150 +#define STM32_CLOCK_BUS_APB4 0x154 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB3 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB4 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32l0_clock.h b/include/dt-bindings/clock/stm32l0_clock.h new file mode 100644 index 0000000000000..b6e8b681d7d8b --- /dev/null +++ b/include/dt-bindings/clock/stm32l0_clock.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L0_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L0_CLOCK_H_ + +/** Peripheral clock sources */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_IOP 0x02c +#define STM32_CLOCK_BUS_AHB1 0x030 +#define STM32_CLOCK_BUS_APB2 0x034 +#define STM32_CLOCK_BUS_APB1 0x038 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_IOP +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB1 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L0_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32l1_clock.h b/include/dt-bindings/clock/stm32l1_clock.h new file mode 100644 index 0000000000000..5fc6155527c1c --- /dev/null +++ b/include/dt-bindings/clock/stm32l1_clock.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L1_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L1_CLOCK_H_ + +/** Peripheral clock sources */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x01c +#define STM32_CLOCK_BUS_APB2 0x020 +#define STM32_CLOCK_BUS_APB1 0x024 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB1 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L1_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32l4_clock.h b/include/dt-bindings/clock/stm32l4_clock.h new file mode 100644 index 0000000000000..71e51ec881a1f --- /dev/null +++ b/include/dt-bindings/clock/stm32l4_clock.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L4_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L4_CLOCK_H_ + +/** Peripheral clock sources */ + +/** 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 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32L4_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32u5_clock.h b/include/dt-bindings/clock/stm32u5_clock.h new file mode 100644 index 0000000000000..4e02e83270252 --- /dev/null +++ b/include/dt-bindings/clock/stm32u5_clock.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32U5_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32U5_CLOCK_H_ + +/** Peripheral clock sources */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x088 +#define STM32_CLOCK_BUS_AHB2 0x08C +#define STM32_CLOCK_BUS_AHB2_2 0x090 +#define STM32_CLOCK_BUS_AHB3 0x094 +#define STM32_CLOCK_BUS_APB1 0x09C +#define STM32_CLOCK_BUS_APB1_2 0x0A0 +#define STM32_CLOCK_BUS_APB2 0x0A4 +#define STM32_CLOCK_BUS_APB3 0x0A8 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32U5_CLOCK_H_ */ diff --git a/include/dt-bindings/clock/stm32wl_clock.h b/include/dt-bindings/clock/stm32wl_clock.h new file mode 100644 index 0000000000000..3c2a7b581d9d8 --- /dev/null +++ b/include/dt-bindings/clock/stm32wl_clock.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WL_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WL_CLOCK_H_ + +/** Peripheral clock sources */ + +/** 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_CLOCK_BUS_APB3 0x064 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WL_CLOCK_H_ */ diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index b1ee442c635eb..5ac43326fa9fb 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -10,7 +10,35 @@ #define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_STM32_CLOCK_CONTROL_H_ #include + +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32F1X) || \ + defined(CONFIG_SOC_SERIES_STM32F3X) +#include +#elif defined(CONFIG_SOC_SERIES_STM32F2X) || \ + defined(CONFIG_SOC_SERIES_STM32F4X) || \ + defined(CONFIG_SOC_SERIES_STM32F7X) +#include +#elif defined(CONFIG_SOC_SERIES_STM32G0X) +#include +#elif defined(CONFIG_SOC_SERIES_STM32L0X) +#include +#elif defined(CONFIG_SOC_SERIES_STM32L1X) +#include +#elif defined(CONFIG_SOC_SERIES_STM32G4X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) || \ + defined(CONFIG_SOC_SERIES_STM32L5X) || \ + defined(CONFIG_SOC_SERIES_STM32WBX) +#include +#elif defined(CONFIG_SOC_SERIES_STM32WLX) +#include +#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#include +#elif defined(CONFIG_SOC_SERIES_STM32U5X) +#include +#else #include +#endif /** Common clock control device node for all STM32 chips */ #define STM32_CLOCK_CONTROL_NODE DT_NODELABEL(rcc) @@ -26,6 +54,20 @@ #define STM32_CPU1_PRESCALER DT_PROP(DT_NODELABEL(rcc), cpu1_prescaler) #define STM32_CPU2_PRESCALER DT_PROP(DT_NODELABEL(rcc), cpu2_prescaler) +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb_prescaler) +#define STM32_CORE_PRESCALER STM32_AHB_PRESCALER +#elif DT_NODE_HAS_PROP(DT_NODELABEL(rcc), cpu1_prescaler) +#define STM32_CORE_PRESCALER STM32_CPU1_PRESCALER +#endif + +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb3_prescaler) +#define STM32_FLASH_PRESCALER STM32_AHB3_PRESCALER +#elif DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler) +#define STM32_FLASH_PRESCALER STM32_AHB4_PRESCALER +#else +#define STM32_FLASH_PRESCALER STM32_CORE_PRESCALER +#endif + #define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), d1cpre) #define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) #define STM32_D2PPRE1 DT_PROP(DT_NODELABEL(rcc), d2ppre1) @@ -73,11 +115,11 @@ #define STM32_PLL_M_DIVISOR DT_PROP(DT_NODELABEL(pll), div_m) #define STM32_PLL_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul_n) #define STM32_PLL_P_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_p) -#define STM32_PLL_P_DIVISOR DT_PROP(DT_NODELABEL(pll), div_p) +#define STM32_PLL_P_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_p, 1) #define STM32_PLL_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_q) -#define STM32_PLL_Q_DIVISOR DT_PROP(DT_NODELABEL(pll), div_q) +#define STM32_PLL_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_q, 1) #define STM32_PLL_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_r) -#define STM32_PLL_R_DIVISOR DT_PROP(DT_NODELABEL(pll), div_r) +#define STM32_PLL_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_r, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7_pll_clock, okay) @@ -85,22 +127,25 @@ #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_P_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_p) -#define STM32_PLL3_P_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_p) +#define STM32_PLL3_P_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_p, 1) #define STM32_PLL3_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_q) -#define STM32_PLL3_Q_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_q) +#define STM32_PLL3_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_q, 1) #define STM32_PLL3_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_r) -#define STM32_PLL3_R_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_r) +#define STM32_PLL3_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_r, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f1_pll_clock, okay) +#define STM32_PLL_ENABLED 1 #define STM32_PLL_XTPRE DT_PROP(DT_NODELABEL(pll), xtpre) #define STM32_PLL_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul) #elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f0_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f100_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f105_pll_clock, okay) +#define STM32_PLL_ENABLED 1 #define STM32_PLL_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul) #define STM32_PLL_PREDIV DT_PROP(DT_NODELABEL(pll), prediv) #elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l0_pll_clock, okay) +#define STM32_PLL_ENABLED 1 #define STM32_PLL_DIVISOR DT_PROP(DT_NODELABEL(pll), div) #define STM32_PLL_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul) #endif @@ -155,6 +200,20 @@ #define STM32_MSIS_ENABLED 1 #define STM32_MSIS_RANGE DT_PROP(DT_NODELABEL(clk_msis), msi_range) #define STM32_MSIS_PLL_MODE DT_PROP(DT_NODELABEL(clk_msis), msi_pll_mode) +#else +#define STM32_MSIS_ENABLED 0 +#define STM32_MSIS_RANGE 0 +#define STM32_MSIS_PLL_MODE 0 +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_msik), st_stm32u5_msi_clock, okay) +#define STM32_MSIK_ENABLED 1 +#define STM32_MSIK_RANGE DT_PROP(DT_NODELABEL(clk_msik), msi_range) +#define STM32_MSIK_PLL_MODE DT_PROP(DT_NODELABEL(clk_msik), msi_pll_mode) +#else +#define STM32_MSIK_ENABLED 0 +#define STM32_MSIK_RANGE 0 +#define STM32_MSIK_PLL_MODE 0 #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_csi), fixed_clock, okay) @@ -171,7 +230,10 @@ #define STM32_LSI_FREQ 0 #endif -#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hsi), st_stm32h7_hsi_clock, okay) +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hsi), fixed_clock, okay) +#define STM32_HSI_ENABLED 1 +#define STM32_HSI_FREQ DT_PROP(DT_NODELABEL(clk_hsi), clock_frequency) +#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hsi), st_stm32h7_hsi_clock, okay) #define STM32_HSI_ENABLED 1 #define STM32_HSI_DIVISOR DT_PROP(DT_NODELABEL(clk_hsi), hsi_div) #define STM32_HSI_FREQ DT_PROP(DT_NODELABEL(clk_hsi), clock_frequency) @@ -180,7 +242,10 @@ #define STM32_HSI_FREQ 0 #endif -#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32_hse_clock, okay) +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), fixed_clock, okay) +#define STM32_HSE_ENABLED 1 +#define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) +#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32_hse_clock, okay) #define STM32_HSE_ENABLED 1 #define STM32_HSE_BYPASS DT_PROP(DT_NODELABEL(clk_hse), hse_bypass) #define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/boards/f2_f4_f7_pll_100_hsi_16_ahb_2.overlay b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/boards/f2_f4_f7_pll_100_hsi_16_ahb_2.overlay new file mode 100644 index 0000000000000..6f6883165223f --- /dev/null +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/boards/f2_f4_f7_pll_100_hsi_16_ahb_2.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Warning: This overlay performs configuration from clean sheet. + * It is assumed that it is applied after clear_clocks.overlay file. + */ + +&clk_hsi { + status = "okay"; +}; + +&pll { + div-m = <8>; + mul-n = <200>; + div-p = <4>; + clocks = <&clk_hsi>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + ahb-prescaler = <2>; + clock-frequency = ; /* Pll Output (100) / AHB prescaler */ + apb1-prescaler = <2>; + apb2-prescaler = <2>; +}; diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/src/test_stm32_clock_configuration.c b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/src/test_stm32_clock_configuration.c index 8179114afd52c..c214fccc22b60 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/src/test_stm32_clock_configuration.c +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/src/test_stm32_clock_configuration.c @@ -8,19 +8,27 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(test); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || \ + defined(CONFIG_SOC_SERIES_STM32WLX) +#define CALC_HCLK_FREQ __LL_RCC_CALC_HCLK1_FREQ +#else +#define CALC_HCLK_FREQ __LL_RCC_CALC_HCLK_FREQ +#endif -static void test_sysclk_freq(void) +static void test_hclk_freq(void) { - uint32_t soc_sys_clk_freq; + uint32_t soc_hclk_freq; - soc_sys_clk_freq = HAL_RCC_GetSysClockFreq(); + soc_hclk_freq = CALC_HCLK_FREQ(HAL_RCC_GetSysClockFreq(), + LL_RCC_GetAHBPrescaler()); - zassert_equal(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_sys_clk_freq, - "Expected sysclockfreq: %d. Actual sysclockfreq: %d", - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_sys_clk_freq); + zassert_equal(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_hclk_freq, + "Expected hclck_freq: %d. Actual hclck_freq: %d", + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_hclk_freq); } static void test_sysclk_src(void) @@ -102,7 +110,7 @@ void test_main(void) { printk("testing clock config on %s\n", CONFIG_BOARD); ztest_test_suite(test_stm32_syclck_config, - ztest_unit_test(test_sysclk_freq), + ztest_unit_test(test_hclk_freq), ztest_unit_test(test_sysclk_src), ztest_unit_test(test_pll_src) ); diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/testcase.yaml index dfbcb952a0d87..6d48812708ad7 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common/testcase.yaml @@ -18,7 +18,7 @@ tests: platform_allow: disco_l475_iot1 nucleo_l4r5zi stm32l562e_dk nucleo_wb55rg nucleo_wl55jc drivers.stm32_clock_configuration.common.sysclksrc_msi_48: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/msi_range11.overlay" - platform_allow: disco_l475_iot1 nucleo_l4r5zi stm32l562e_dk nucleo_l152re nucleo_l073rz nucleo_wl55jc nucleo_wb55rg + platform_allow: disco_l475_iot1 nucleo_l4r5zi stm32l562e_dk nucleo_wl55jc nucleo_wb55rg drivers.stm32_clock_configuration.common.l4_l5.sysclksrc_hse_8.fixup: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/hse_8.overlay" platform_allow: disco_l475_iot1 nucleo_l4r5zi stm32l562e_dk @@ -92,12 +92,12 @@ tests: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/f0_f3_pll_32_hse_8.overlay" platform_allow: nucleo_f091rc stm32f3_disco drivers.stm32_clock_configuration.common.f1.sysclksrc_hsi_8: - extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hsi_16.overlay" + extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hsi_8.overlay" platform_allow: nucleo_f103rb drivers.stm32_clock_configuration.common.f1.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/hse_8.overlay" platform_allow: nucleo_f103rb - drivers.stm32_clock_configuration.common.f1.sysclksrc_pll_64_hsi_16: + drivers.stm32_clock_configuration.common.f1.sysclksrc_pll_64_hsi_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f0_f1_f3_clocks.overlay;boards/f1_pll_64_hsi_8.overlay" platform_allow: nucleo_f103rb drivers.stm32_clock_configuration.common.f1.sysclksrc_pll_64_hse_8: @@ -115,3 +115,6 @@ tests: drivers.stm32_clock_configuration.common.f2_f4_f7.sysclksrc_pll_64_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/f2_f4_f7_pll_64_hse_8.overlay" platform_allow: nucleo_f207zg nucleo_f429zi nucleo_f446re nucleo_f746zg + drivers.stm32_clock_configuration.common.f2_f4_f7.sysclksrc_pll_100_hsi_16_ahb2: + extra_args: DTC_OVERLAY_FILE="boards/clear_f2_f4_f7_clocks.overlay;boards/f2_f4_f7_pll_100_hsi_16_ahb_2.overlay" + platform_allow: nucleo_f207zg nucleo_f429zi nucleo_f446re nucleo_f746zg diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_msis_80.overlay b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_msis_ahb_2_80.overlay similarity index 84% rename from tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_msis_80.overlay rename to tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_msis_ahb_2_80.overlay index d3aa904ade390..d9c41e27f6290 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_msis_80.overlay +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/boards/pll_msis_ahb_2_80.overlay @@ -20,9 +20,9 @@ }; &pll1 { - div-m = <2>; + div-m = <1>; mul-n = <40>; - div-q = <2>; + div-q = <1>; div-r = <1>; clocks = <&clk_msis>; status = "okay"; @@ -30,8 +30,8 @@ &rcc { clocks = <&pll1>; + ahb-prescaler = <2>; /* Use AHB prescaler to reduce HCLK */ clock-frequency = ; - ahb-prescaler = <1>; apb1-prescaler = <1>; apb2-prescaler = <1>; apb3-prescaler = <1>; diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/src/test_stm32_clock_configuration.c b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/src/test_stm32_clock_configuration.c index 351f60c7e2bf8..3a2af7b5469d7 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/src/test_stm32_clock_configuration.c +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/src/test_stm32_clock_configuration.c @@ -11,15 +11,15 @@ #include LOG_MODULE_REGISTER(test); -static void test_sysclk_freq(void) +static void test_hclk_freq(void) { - uint32_t soc_sys_clk_freq; + uint32_t soc_hclk_freq; - soc_sys_clk_freq = HAL_RCC_GetSysClockFreq(); + soc_hclk_freq = HAL_RCC_GetHCLKFreq(); - zassert_equal(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_sys_clk_freq, - "Expected sysclockfreq: %d. Actual sysclockfreq: %d", - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_sys_clk_freq); + zassert_equal(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_hclk_freq, + "Expected hclk_freq: %d. Actual hclk_freq: %d", + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, soc_hclk_freq); } static void test_sysclk_src(void) @@ -80,7 +80,7 @@ static void test_pll_src(void) void test_main(void) { ztest_test_suite(test_stm32_syclck_config, - ztest_unit_test(test_sysclk_freq), + ztest_unit_test(test_hclk_freq), ztest_unit_test(test_sysclk_src), ztest_unit_test(test_pll_src) ); diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml index 7a965df8bf638..5298b3416da16 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32u5_core/testcase.yaml @@ -4,8 +4,8 @@ common: tests: drivers.stm32_clock_configuration.u5.sysclksrc_pll_msis_160: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_msis_160.overlay" - drivers.stm32_clock_configuration.u5.sysclksrc_pll_msis_80: - extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_msis_80.overlay" + drivers.stm32_clock_configuration.u5.pll_msis_hab_2_80: + extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_msis_ahb_2_80.overlay" drivers.stm32_clock_configuration.u5.sysclksrc_pll_hsi_160: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_hsi_160.overlay" drivers.stm32_clock_configuration.u5.sysclksrc_pll_hsi_40: