Skip to content
Permalink
Browse files

drivers/clock_control: Add support to stm32wb series

Add support to stm32wb series in stm32 clock_control driver.
Ip is similar to stm32l4 one but AHB bus presacler is renamed
to "CPU1" and CPU2 and AHB4 prescalers should be defined.

Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
  • Loading branch information...
erwango authored and galak committed Feb 25, 2019
1 parent 7117f1c commit b11289997f3dab4d226ae7a8ae206ed5f4583801
@@ -18,4 +18,5 @@ if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F7X stm32f7x_ll_clock.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32L0X stm32l0x_ll_clock.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32L4X stm32l4x_ll_clock.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32WBX stm32wbx_ll_clock.c)
endif()
@@ -42,7 +42,7 @@ config CLOCK_STM32_SYSCLK_SRC_HSI

config CLOCK_STM32_SYSCLK_SRC_MSI
bool "MSI"
depends on SOC_SERIES_STM32L0X || SOC_SERIES_STM32L4X
depends on SOC_SERIES_STM32L0X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX
help
Use MSI as source of SYSCLK

@@ -92,7 +92,7 @@ default CLOCK_STM32_PLL_SRC_HSI

config CLOCK_STM32_PLL_SRC_MSI
bool "MSI"
depends on SOC_SERIES_STM32L0X || SOC_SERIES_STM32L4X
depends on SOC_SERIES_STM32L0X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX
help
Use MSI as source of PLL

@@ -321,7 +321,7 @@ config CLOCK_STM32_PLL_DIVISOR

endif # SOC_SERIES_STM32L0X

if SOC_SERIES_STM32L4X
if SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX

config CLOCK_STM32_PLL_M_DIVISOR
int "PLL divisor"
@@ -377,12 +377,13 @@ config CLOCK_STM32_MSI_PLL_MODE
help
Enable hardware auto-calibration with LSE.

endif # SOC_SERIES_STM32L4X
endif # SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX

config CLOCK_STM32_AHB_PRESCALER
int "AHB prescaler"
default 1
range 1 512
depends on !SOC_SERIES_STM32WBX
help
AHB prescaler, allowed values: 1, 2, 4, 8, 16, 64, 128,
256, 512.
@@ -407,6 +408,34 @@ config CLOCK_STM32_APB2_PRESCALER

endif # SOC_SERIES_STM32F0X!=y

if SOC_SERIES_STM32WBX

config CLOCK_STM32_CPU1_PRESCALER
int "CPU1 HCLK prescaler"
default 1
range 1 512
help
CPU1 HCLK prescaler, allowed values: 1, 2, 4, 8, 16, 64, 128,
256, 512.

config CLOCK_STM32_CPU2_PRESCALER
int "CPU2 HCLK prescaler"
default 1
range 1 512
help
CPU2 HCLK prescaler, allowed values: 1, 2, 4, 8, 16, 64, 128,
256, 512.

config CLOCK_STM32_AHB4_PRESCALER
int "AHB4 HCLK prescaler"
default 1
range 1 512
help
HCLK4 prescaler, allowed values: 1, 2, 4, 8, 16, 64, 128,
256, 512.

endif # SOC_SERIES_STM32WBX

choice
prompt "STM32 MCO1 Clock Source"
default CLOCK_STM32_MCO1_SRC_NOCLOCK
@@ -31,15 +31,30 @@
#define z_mco2_prescaler(v) LL_RCC_MCO2_DIV_ ## v
#define mco2_prescaler(v) z_mco2_prescaler(v)

#ifdef CONFIG_SOC_SERIES_STM32WBX
#define __LL_RCC_CALC_HCLK_FREQ __LL_RCC_CALC_HCLK1_FREQ
#endif /* CONFIG_SOC_SERIES_STM32F0X */

/**
* @brief fill in AHB/APB buses configuration structure
*/
static void config_bus_clk_init(LL_UTILS_ClkInitTypeDef *clk_init)
{
#ifdef CONFIG_SOC_SERIES_STM32WBX
clk_init->CPU1CLKDivider = ahb_prescaler(
CONFIG_CLOCK_STM32_CPU1_PRESCALER);
clk_init->CPU2CLKDivider = ahb_prescaler(
CONFIG_CLOCK_STM32_CPU2_PRESCALER);
clk_init->AHB4CLKDivider = ahb_prescaler(
CONFIG_CLOCK_STM32_AHB4_PRESCALER);
#else
clk_init->AHBCLKDivider = ahb_prescaler(
CONFIG_CLOCK_STM32_AHB_PRESCALER);
#endif /* CONFIG_SOC_SERIES_STM32WBX */

clk_init->APB1CLKDivider = apb1_prescaler(
CONFIG_CLOCK_STM32_APB1_PRESCALER);

#ifndef CONFIG_SOC_SERIES_STM32F0X
clk_init->APB2CLKDivider = apb2_prescaler(
CONFIG_CLOCK_STM32_APB2_PRESCALER);
@@ -65,7 +80,8 @@ static inline int stm32_clock_control_on(struct device *dev,
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32F2X)
defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32WBX)
case STM32_CLOCK_BUS_AHB2:
LL_AHB2_GRP1_EnableClock(pclken->enr);
break;
@@ -74,7 +90,9 @@ static inline int stm32_clock_control_on(struct device *dev,
case STM32_CLOCK_BUS_APB1:
LL_APB1_GRP1_EnableClock(pclken->enr);
break;
#if defined(CONFIG_SOC_SERIES_STM32L4X) || defined(CONFIG_SOC_SERIES_STM32F0X)
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32WBX)
case STM32_CLOCK_BUS_APB1_2:
LL_APB1_GRP2_EnableClock(pclken->enr);
break;
@@ -120,7 +138,9 @@ static inline int stm32_clock_control_off(struct device *dev,
case STM32_CLOCK_BUS_APB1:
LL_APB1_GRP1_DisableClock(pclken->enr);
break;
#if defined(CONFIG_SOC_SERIES_STM32L4X) || defined(CONFIG_SOC_SERIES_STM32F0X)
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32WBX)
case STM32_CLOCK_BUS_APB1_2:
LL_APB1_GRP2_DisableClock(pclken->enr);
break;
@@ -173,9 +193,11 @@ static int stm32_clock_control_get_subsys_rate(struct device *clock,
*rate = ahb_clock;
break;
case STM32_CLOCK_BUS_APB1:
#if defined(CONFIG_SOC_SERIES_STM32L4X) || defined(CONFIG_SOC_SERIES_STM32F0X)
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32WBX)
case STM32_CLOCK_BUS_APB1_2:
#endif /* CONFIG_SOC_SERIES_STM32L4X || CONFIG_SOC_SERIES_STM32F0X */
#endif
*rate = apb1_clock;
break;
#ifndef CONFIG_SOC_SERIES_STM32F0X
@@ -238,12 +260,20 @@ static inline void stm32_clock_control_mco_init(void)
static int stm32_clock_control_init(struct device *dev)
{
LL_UTILS_ClkInitTypeDef s_ClkInitStruct;
u32_t hclk_prescaler;

ARG_UNUSED(dev);

/* configure clock for AHB/APB buses */
config_bus_clk_init((LL_UTILS_ClkInitTypeDef *)&s_ClkInitStruct);

/* update local hclk prescaler variable */
#ifdef CONFIG_SOC_SERIES_STM32WBX
hclk_prescaler = s_ClkInitStruct.CPU1CLKDivider;
#else
hclk_prescaler = s_ClkInitStruct.AHBCLKDivider;
#endif /* CONFIG_SOC_SERIES_STM32WBX */

/* Some clocks would be activated by default */
config_enable_default_clocks();

@@ -302,9 +332,13 @@ static int stm32_clock_control_init(struct device *dev)
#endif /* CONFIG_CLOCK_STM32_HSE_BYPASS */

/* Switch to PLL with HSE as clock source */
LL_PLL_ConfigSystemClock_HSE(CONFIG_CLOCK_STM32_HSE_CLOCK, hse_bypass,
&s_PLLInitStruct,
&s_ClkInitStruct);
LL_PLL_ConfigSystemClock_HSE(
#ifndef CONFIG_SOC_SERIES_STM32WBX
CONFIG_CLOCK_STM32_HSE_CLOCK,
#endif
hse_bypass,
&s_PLLInitStruct,
&s_ClkInitStruct);

/* Disable other clocks */
LL_RCC_HSI_Disable();
@@ -332,14 +366,14 @@ static int stm32_clock_control_init(struct device *dev)

/* Set HSE as SYSCLCK source */
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
LL_RCC_SetAHBPrescaler(s_ClkInitStruct.AHBCLKDivider);
LL_RCC_SetAHBPrescaler(hclk_prescaler);
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {
}

/* Update SystemCoreClock variable */
LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK_FREQ(
CONFIG_CLOCK_STM32_HSE_CLOCK,
s_ClkInitStruct.AHBCLKDivider));
hclk_prescaler));

/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
@@ -377,7 +411,7 @@ static int stm32_clock_control_init(struct device *dev)

/* Set MSI as SYSCLCK source */
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI);
LL_RCC_SetAHBPrescaler(s_ClkInitStruct.AHBCLKDivider);
LL_RCC_SetAHBPrescaler(hclk_prescaler);
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) {
}

@@ -389,6 +423,11 @@ static int stm32_clock_control_init(struct device *dev)
/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider);
#ifdef CONFIG_SOC_SERIES_STM32WBX
/* Set C2 AHB & AHB4 prescalers */
LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct->CPU2CLKDivider);
LL_RCC_SetAHB4Prescaler(s_ClkInitStruct->AHB4CLKDivider);
#endif /* CONFIG_SOC_SERIES_STM32WBX */

/* Set flash latency */
/* MSI used as SYSCLK (16MHz), set latency to 0 */
@@ -401,11 +440,11 @@ static int stm32_clock_control_init(struct device *dev)

#elif CONFIG_CLOCK_STM32_SYSCLK_SRC_HSI

stm32_clock_switch_to_hsi(s_ClkInitStruct.AHBCLKDivider);
stm32_clock_switch_to_hsi(hclk_prescaler);

/* Update SystemCoreClock variable */
LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK_FREQ(HSI_VALUE,
s_ClkInitStruct.AHBCLKDivider));
hclk_prescaler));

/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
@@ -0,0 +1,43 @@
/*
*
* Copyright (c) 2019 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 _pllr(v) LL_RCC_PLLR_DIV_ ## v
#define pllr(v) _pllr(v)


/**
* @brief fill in pll configuration structure
*/
void config_pll_init(LL_UTILS_PLLInitTypeDef *pllinit)
{
pllinit->PLLM = pllm(CONFIG_CLOCK_STM32_PLL_M_DIVISOR);
pllinit->PLLN = CONFIG_CLOCK_STM32_PLL_N_MULTIPLIER;
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 */
}
@@ -38,6 +38,14 @@
label = "FLASH_STM32";
};
};

rcc: rcc@58000000 {
compatible = "st,stm32-rcc";
clocks-controller;
#clock-cells = <2>;
reg = <0x58000000 0x400>;
label = "STM32_CLK_RCC";
};
};
};

@@ -13,5 +13,6 @@ config SOC_SERIES_STM32WBX
select HAS_STM32CUBE
select CPU_HAS_ARM_MPU
select CPU_HAS_SYSTICK
select CLOCK_CONTROL_STM32_CUBE if CLOCK_CONTROL
help
Enable support for STM32WB MCU series
@@ -7,6 +7,10 @@
/**
* @file SoC configuration macros for the STM32WB family processors.
*
* Based on reference manual:
* TODO: Provide reference when known
*
* Chapter 2.2.2: Memory map and register boundary addresses
*/


@@ -23,6 +27,13 @@
*/
#include <kernel_includes.h>

#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
#include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_system.h>
#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */

#endif /* !_ASMLANGUAGE */

#endif /* _STM32WBX_SOC_H_ */

0 comments on commit b112899

Please sign in to comment.
You can’t perform that action at this time.