From fda01e52c2f6f3f55671334abd352ced8a89a565 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Tue, 18 Apr 2017 14:24:04 +0200 Subject: [PATCH] drivers: clock control: Provide LL based clock control for stm32f4 series This commit enables STM32Cube LL based driver for stm32f4 series. This generic driver provides a unified API to clock driver for all stm32 series. LL API allows driver to be lightweight and to keep genericity across stm32 family to ease further devlopment and maintenance. Change-Id: Ie31ae8f433313787f9c9eda77de41925721d54dd Signed-off-by: Erwan Gouriou --- .../st_stm32/stm32f4/Kconfig.defconfig.series | 3 ++ arch/arm/soc/st_stm32/stm32f4/soc.c | 6 +++ arch/arm/soc/st_stm32/stm32f4/soc.h | 7 +++ arch/arm/soc/st_stm32/stm32f4/soc_gpio.c | 7 +++ drivers/clock_control/Kconfig.stm32 | 46 ++++++++++++++++ drivers/clock_control/Makefile | 1 + drivers/clock_control/stm32_ll_clock.c | 9 ++++ drivers/clock_control/stm32_ll_clock.h | 1 + drivers/clock_control/stm32f3x_ll_clock.c | 8 +++ drivers/clock_control/stm32f4x_ll_clock.c | 52 +++++++++++++++++++ drivers/clock_control/stm32l4x_ll_clock.c | 8 +++ drivers/gpio/gpio_stm32.h | 2 +- ext/hal/st/stm32cube/Kbuild | 1 + 13 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 drivers/clock_control/stm32f4x_ll_clock.c diff --git a/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series b/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series index f2571985945..c1278c1f551 100644 --- a/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series +++ b/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series @@ -45,6 +45,9 @@ if CLOCK_CONTROL config CLOCK_CONTROL_STM32F4X def_bool y +config CLOCK_CONTROL_STM32_CUBE + def_bool n + endif #CLOCK_CONTROL if GPIO diff --git a/arch/arm/soc/st_stm32/stm32f4/soc.c b/arch/arm/soc/st_stm32/stm32f4/soc.c index f1e4d693acc..e2e27cee9e1 100644 --- a/arch/arm/soc/st_stm32/stm32f4/soc.c +++ b/arch/arm/soc/st_stm32/stm32f4/soc.c @@ -53,8 +53,14 @@ static int st_stm32f4_init(struct device *arg) irq_unlock(key); +#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE + /* Update CMSIS SystemCoreClock variable (HCLK) */ + /* At reset, System core clock is set to 4MHz */ + SystemCoreClock = 4000000; +#else /* Update CMSIS SystemCoreClock variable (HCLK) */ SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; +#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */ return 0; } diff --git a/arch/arm/soc/st_stm32/stm32f4/soc.h b/arch/arm/soc/st_stm32/stm32f4/soc.h index 372d2afcff1..d611d1b07e5 100644 --- a/arch/arm/soc/st_stm32/stm32f4/soc.h +++ b/arch/arm/soc/st_stm32/stm32f4/soc.h @@ -52,6 +52,13 @@ enum stm32f4x_pin_config_mode { #include "soc_irq.h" +#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE +#include +#include +#include +#include +#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */ + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F4_SOC_H_ */ diff --git a/arch/arm/soc/st_stm32/stm32f4/soc_gpio.c b/arch/arm/soc/st_stm32/stm32f4/soc_gpio.c index 388be15121d..44098169d44 100644 --- a/arch/arm/soc/st_stm32/stm32f4/soc_gpio.c +++ b/arch/arm/soc/st_stm32/stm32f4/soc_gpio.c @@ -234,10 +234,17 @@ int stm32_gpio_enable_int(int port, int pin) (struct stm32f4x_syscfg *)SYSCFG_BASE; volatile union syscfg_exticr *exticr; struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); +#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE + struct stm32_pclken pclken = { + .bus = STM32_CLOCK_BUS_APB2, + .enr = LL_APB2_GRP1_PERIPH_SYSCFG + }; +#else struct stm32f4x_pclken pclken = { .bus = STM32F4X_CLOCK_BUS_APB2, .enr = STM32F4X_CLOCK_ENABLE_SYSCFG }; +#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */ int shift = 0; /* Enable SYSCFG clock */ diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 293aaed0175..f14242a073e 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -110,6 +110,52 @@ config CLOCK_STM32_PLL_MULTIPLIER endif # SOC_SERIES_STM32F3X +if SOC_SERIES_STM32F4X + +config CLOCK_STM32_PLLM_DIV_FACTOR + int "Division factor for PLL VCO input clock" + depends on CLOCK_CONTROL_STM32_CUBE && CLOCK_STM32_SYSCLK_SRC_PLL + default 8 + range 2 63 + help + PLLM division factor needs to be set correctly to ensure that the VCO + input frequency ranges from 1 to 2 MHz. It is recommended to select a + frequency of 2 MHz to limit PLL jitter. + Allowed values: 2-63 + +config CLOCK_STM32_PLLN_MULTIPLIER + int "Multiplier factor for PLL VCO output clock" + depends on CLOCK_CONTROL_STM32_CUBE && CLOCK_STM32_SYSCLK_SRC_PLL + default 336 + range 192 432 if SOC_STM32F401XE + range 50 432 + help + PLLN multiplier factor needs to be set correctly to ensure that the + VCO output frequency is between 100 and 432 MHz, except on STM32F401 + where the frequency must be between 192 and 432 MHz. + Allowed values: 50-432 (STM32F401: 192-432) + +config CLOCK_STM32_PLLP_DIV_FACTOR + int "PLL division factor for main system clock" + depends on CLOCK_CONTROL_STM32_CUBE && CLOCK_STM32_SYSCLK_SRC_PLL + default 4 + range 2 8 + help + PLLP division factor needs to be set correctly to not exceed 84MHz. + Allowed values: 2, 4, 6, 8 + +config CLOCK_STM32_PLLQ_DIV_FACTOR + int "Division factor for OTG FS, SDIO and RNG clocks" + depends on CLOCK_CONTROL_STM32_CUBE && CLOCK_STM32_SYSCLK_SRC_PLL + default 7 + range 2 15 + help + The USB OTG FS requires a 48MHz clock to work correctly. SDIO and RNG + need a frequency lower than or equal to 48 MHz to work correctly. + Allowed values: 2-15 + +endif # SOC_SERIES_STM32F4X + if SOC_SERIES_STM32L4X config CLOCK_STM32_PLL_M_DIVISOR diff --git a/drivers/clock_control/Makefile b/drivers/clock_control/Makefile index 5fdb1ec073c..13574177a85 100644 --- a/drivers/clock_control/Makefile +++ b/drivers/clock_control/Makefile @@ -4,6 +4,7 @@ ifeq ($(CONFIG_CLOCK_CONTROL_STM32_CUBE),y) obj-y += stm32_ll_clock.o obj-$(CONFIG_SOC_SERIES_STM32L4X) += stm32l4x_ll_clock.o obj-$(CONFIG_SOC_SERIES_STM32F3X) += stm32f3x_ll_clock.o +obj-$(CONFIG_SOC_SERIES_STM32F4X) += stm32f4x_ll_clock.o else obj-$(CONFIG_CLOCK_CONTROL_STM32F10X) += stm32f10x_clock.o obj-$(CONFIG_CLOCK_CONTROL_STM32F10X_CONN_LINE) += stm32f107xx_clock.o diff --git a/drivers/clock_control/stm32_ll_clock.c b/drivers/clock_control/stm32_ll_clock.c index a5f67c359ba..58ee8cf16a0 100644 --- a/drivers/clock_control/stm32_ll_clock.c +++ b/drivers/clock_control/stm32_ll_clock.c @@ -159,6 +159,9 @@ static int stm32_clock_control_init(struct device *dev) /* configure clock for AHB/APB buses */ config_bus_clk_init((LL_UTILS_ClkInitTypeDef *)&s_ClkInitStruct); + /* Some clocks would be activated by default */ + config_enable_default_clocks(); + #ifdef CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL LL_UTILS_PLLInitTypeDef s_PLLInitStruct; @@ -168,6 +171,12 @@ static int stm32_clock_control_init(struct device *dev) /* Disable PLL before configuration */ LL_RCC_PLL_Disable(); +#ifdef CONFIG_CLOCK_STM32_PLLQ_DIV_FACTOR + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ, + CONFIG_CLOCK_STM32_PLLQ_DIV_FACTOR + << POSITION_VAL(RCC_PLLCFGR_PLLQ)); +#endif /* CONFIG_CLOCK_STM32_PLLQ_DIV_FACTOR */ + #ifdef CONFIG_CLOCK_STM32_PLL_SRC_MSI /* Switch to PLL with MSI as clock source */ LL_PLL_ConfigSystemClock_MSI(&s_PLLInitStruct, &s_ClkInitStruct); diff --git a/drivers/clock_control/stm32_ll_clock.h b/drivers/clock_control/stm32_ll_clock.h index 73d090b24a4..73f98e53333 100644 --- a/drivers/clock_control/stm32_ll_clock.h +++ b/drivers/clock_control/stm32_ll_clock.h @@ -9,6 +9,7 @@ #define _STM32_LL_CLOCK_H_ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit); +void config_enable_default_clocks(void); /* Section for functions not available in every Cube packages */ void LL_RCC_MSI_Disable(void); diff --git a/drivers/clock_control/stm32f3x_ll_clock.c b/drivers/clock_control/stm32f3x_ll_clock.c index 742bf636b53..543f809c263 100644 --- a/drivers/clock_control/stm32f3x_ll_clock.c +++ b/drivers/clock_control/stm32f3x_ll_clock.c @@ -64,6 +64,14 @@ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) #endif /* CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL */ +/** + * @brief Activate default clocks + */ +void config_enable_default_clocks(void) +{ + /* Nothing for now */ +} + /** * @brief Function kept for driver genericity */ diff --git a/drivers/clock_control/stm32f4x_ll_clock.c b/drivers/clock_control/stm32f4x_ll_clock.c new file mode 100644 index 00000000000..bd49bdc0d05 --- /dev/null +++ b/drivers/clock_control/stm32f4x_ll_clock.c @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2017 Linaro Limited. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include +#include +#include +#include +#include "stm32_ll_clock.h" + + +#ifdef CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL + +/* Macros to fill up division factors values */ +#define _pllm(v) LL_RCC_PLLM_DIV_ ## v +#define pllm(v) _pllm(v) + +#define _pllp(v) LL_RCC_PLLP_DIV_ ## v +#define pllp(v) _pllp(v) + +/** + * @brief fill in pll configuration structure + */ +void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) +{ + pllinit->PLLM = pllm(CONFIG_CLOCK_STM32_PLLM_DIV_FACTOR); + pllinit->PLLN = CONFIG_CLOCK_STM32_PLLN_MULTIPLIER; + pllinit->PLLP = pllp(CONFIG_CLOCK_STM32_PLLP_DIV_FACTOR); +} +#endif /* CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL */ + +/** + * @brief Activate default clocks + */ +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/stm32l4x_ll_clock.c b/drivers/clock_control/stm32l4x_ll_clock.c index b976523598d..075f9f31779 100644 --- a/drivers/clock_control/stm32l4x_ll_clock.c +++ b/drivers/clock_control/stm32l4x_ll_clock.c @@ -33,3 +33,11 @@ void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit) pllinit->PLLR = pllr(CONFIG_CLOCK_STM32_PLL_R_DIVISOR); } #endif /* CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL */ + +/** + * @brief Activate default clocks + */ +void config_enable_default_clocks(void) +{ + /* Nothing for now */ +} diff --git a/drivers/gpio/gpio_stm32.h b/drivers/gpio/gpio_stm32.h index d89fb7cc76e..a1cbe85e122 100644 --- a/drivers/gpio/gpio_stm32.h +++ b/drivers/gpio/gpio_stm32.h @@ -18,7 +18,7 @@ #ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE /* GPIO buses definitions */ -#ifdef CONFIG_SOC_SERIES_STM32F3X +#if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F4X) #define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_AHB1 #define STM32_PERIPH_GPIOA LL_AHB1_GRP1_PERIPH_GPIOA #define STM32_PERIPH_GPIOB LL_AHB1_GRP1_PERIPH_GPIOB diff --git a/ext/hal/st/stm32cube/Kbuild b/ext/hal/st/stm32cube/Kbuild index b0c38c0bbe4..5d49ef33e37 100644 --- a/ext/hal/st/stm32cube/Kbuild +++ b/ext/hal/st/stm32cube/Kbuild @@ -19,6 +19,7 @@ endif ifdef CONFIG_SOC_SERIES_STM32F4X obj-y += stm32f4xx/drivers/src/stm32f4xx_hal.o obj-y += stm32f4xx/drivers/src/stm32f4xx_hal_rcc.o +obj-$(CONFIG_CLOCK_CONTROL_STM32_CUBE) += stm32f4xx/drivers/src/stm32f4xx_ll_utils.o obj-$(CONFIG_PWM) += stm32f4xx/drivers/src/stm32f4xx_hal_tim.o obj-$(CONFIG_SERIAL_HAS_DRIVER) += stm32f4xx/drivers/src/stm32f4xx_hal_uart.o obj-y += stm32f4xx/soc/system_stm32f4xx.o