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 <erwan.gouriou@linaro.org>
This commit is contained in:
Erwan Gouriou 2017-04-18 14:24:04 +02:00 committed by Kumar Gala
commit fda01e52c2
13 changed files with 150 additions and 1 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -52,6 +52,13 @@ enum stm32f4x_pin_config_mode {
#include "soc_irq.h"
#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
#include <stm32f4xx_ll_utils.h>
#include <stm32f4xx_ll_bus.h>
#include <stm32f4xx_ll_rcc.h>
#include <stm32f4xx_ll_system.h>
#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */
#endif /* !_ASMLANGUAGE */
#endif /* _STM32F4_SOC_H_ */

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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
*/

View file

@ -0,0 +1,52 @@
/*
*
* Copyright (c) 2017 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <soc.h>
#include <soc_registers.h>
#include <clock_control.h>
#include <misc/util.h>
#include <clock_control/stm32_clock_control.h>
#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 */
}

View file

@ -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 */
}

View file

@ -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

View file

@ -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