clock/stm32: add STM32F107 reset and clock control
Change-Id: If2280187c866c130212ea22c3d406501f37133b2 Signed-off-by: Adam Podogrocki <adam.podogrocki@rndity.com>
This commit is contained in:
parent
10b350d854
commit
72782f542c
7 changed files with 653 additions and 8 deletions
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
||||||
|
* Copyright (c) 2016 RnDity Sp. z o.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -26,9 +27,11 @@
|
||||||
*
|
*
|
||||||
* Chapter 7: Low-, medium-, high- and XL-density reset and
|
* Chapter 7: Low-, medium-, high- and XL-density reset and
|
||||||
* clock control
|
* clock control
|
||||||
|
* Chapter 8: Connectivity line devices: reset and clock control (RCC)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 8.3.1 Clock control register (RCC_CR) */
|
/* 8.3.1 Clock control register (RCC_CR) */
|
||||||
|
#ifdef CONFIG_SOC_STM32F10X_DENSITY_DEVICE
|
||||||
enum {
|
enum {
|
||||||
STM32F10X_RCC_CFG_PLL_SRC_HSI = 0x0,
|
STM32F10X_RCC_CFG_PLL_SRC_HSI = 0x0,
|
||||||
STM32F10X_RCC_CFG_PLL_SRC_HSE = 0x1,
|
STM32F10X_RCC_CFG_PLL_SRC_HSE = 0x1,
|
||||||
|
@ -38,6 +41,7 @@ enum {
|
||||||
STM32F10X_RCC_CFG_PLL_XTPRE_DIV_0 = 0x0,
|
STM32F10X_RCC_CFG_PLL_XTPRE_DIV_0 = 0x0,
|
||||||
STM32F10X_RCC_CFG_PLL_XTPRE_DIV_2 = 0x1,
|
STM32F10X_RCC_CFG_PLL_XTPRE_DIV_2 = 0x1,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STM32F10X_RCC_CFG_SYSCLK_SRC_HSI = 0x0,
|
STM32F10X_RCC_CFG_SYSCLK_SRC_HSI = 0x0,
|
||||||
|
@ -65,6 +69,37 @@ enum {
|
||||||
STM32F10X_RCC_CFG_SYSCLK_DIV_512 = 0xf,
|
STM32F10X_RCC_CFG_SYSCLK_DIV_512 = 0xf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE
|
||||||
|
enum {
|
||||||
|
STM32F10X_RCC_CFG_PLL_SRC_HSI = 0x0,
|
||||||
|
STM32F10X_RCC_CFG_PLL_SRC_PREDIV1 = 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STM32F10X_RCC_CFG2_PREDIV1_SRC_HSE = 0x0,
|
||||||
|
STM32F10X_RCC_CFG2_PREDIV1_SRC_PLL2 = 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_0 = 0x0,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_2 = 0x1,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_3 = 0x2,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_4 = 0x3,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_5 = 0x4,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_6 = 0x5,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_7 = 0x6,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_8 = 0x7,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_9 = 0x8,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_10 = 0x9,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_11 = 0xa,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_12 = 0xb,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_13 = 0xc,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_14 = 0xd,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_15 = 0xe,
|
||||||
|
STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_16 = 0xf
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset and Clock Control
|
* @brief Reset and Clock Control
|
||||||
*/
|
*/
|
||||||
|
@ -84,7 +119,15 @@ union __rcc_cr {
|
||||||
uint32_t rsvd__20_23 :4 __packed;
|
uint32_t rsvd__20_23 :4 __packed;
|
||||||
uint32_t pllon :1 __packed;
|
uint32_t pllon :1 __packed;
|
||||||
uint32_t pllrdy :1 __packed;
|
uint32_t pllrdy :1 __packed;
|
||||||
|
#if CONFIG_SOC_STM32F10X_DENSITY_DEVICE
|
||||||
uint32_t rsvd__26_31 :6 __packed;
|
uint32_t rsvd__26_31 :6 __packed;
|
||||||
|
#elif CONFIG_SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE
|
||||||
|
uint32_t pll2on :1 __packed;
|
||||||
|
uint32_t pll2rdy :1 __packed;
|
||||||
|
uint32_t pll3on :1 __packed;
|
||||||
|
uint32_t pll3rdy :1 __packed;
|
||||||
|
uint32_t rsvd__30_31 :2 __packed;
|
||||||
|
#endif
|
||||||
} bit;
|
} bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,6 +150,20 @@ union __rcc_cfgr {
|
||||||
} bit;
|
} bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union __rcc_cfgr2 {
|
||||||
|
uint32_t val;
|
||||||
|
struct {
|
||||||
|
uint32_t prediv1 :4 __packed;
|
||||||
|
uint32_t prediv2 :4 __packed;
|
||||||
|
uint32_t pll2mul :4 __packed;
|
||||||
|
uint32_t pll3mul :4 __packed;
|
||||||
|
uint32_t prediv1src :1 __packed;
|
||||||
|
uint32_t i2s2sr :1 __packed;
|
||||||
|
uint32_t i2s3sr :1 __packed;
|
||||||
|
uint32_t rsvd__19_31 :13 __packed;
|
||||||
|
} bit;
|
||||||
|
};
|
||||||
|
|
||||||
struct stm32f10x_rcc {
|
struct stm32f10x_rcc {
|
||||||
union __rcc_cr cr;
|
union __rcc_cr cr;
|
||||||
union __rcc_cfgr cfgr;
|
union __rcc_cfgr cfgr;
|
||||||
|
@ -118,6 +175,10 @@ struct stm32f10x_rcc {
|
||||||
uint32_t apb1enr;
|
uint32_t apb1enr;
|
||||||
uint32_t bdcr;
|
uint32_t bdcr;
|
||||||
uint32_t csr;
|
uint32_t csr;
|
||||||
|
#ifdef CONFIG_SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE
|
||||||
|
uint32_t ahbrstr;
|
||||||
|
union __rcc_cfgr2 cfgr2;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _STM32F10X_CLOCK_H_ */
|
#endif /* _STM32F10X_CLOCK_H_ */
|
||||||
|
|
|
@ -50,13 +50,15 @@ config SYS_LOG_CLOCK_CONTROL_LEVEL
|
||||||
|
|
||||||
- 4 DEBUG, write SYS_LOG_DBG in adition to previous levels
|
- 4 DEBUG, write SYS_LOG_DBG in adition to previous levels
|
||||||
|
|
||||||
|
source "drivers/clock_control/Kconfig.nrf5"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.quark_se"
|
source "drivers/clock_control/Kconfig.quark_se"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.stm32f10x"
|
source "drivers/clock_control/Kconfig.stm32f10x"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.stm32f4x"
|
source "drivers/clock_control/Kconfig.stm32f107xx"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.nrf5"
|
source "drivers/clock_control/Kconfig.stm32f4x"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.stm32l4x"
|
source "drivers/clock_control/Kconfig.stm32l4x"
|
||||||
|
|
||||||
|
|
157
drivers/clock_control/Kconfig.stm32f107xx
Normal file
157
drivers/clock_control/Kconfig.stm32f107xx
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
# Kconfig - STM32F1X Connectivity Line MCU clock control driver config
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 RnDity Sp. z o.o.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
if SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE
|
||||||
|
|
||||||
|
menuconfig CLOCK_CONTROL_STM32F10X_CONN_LINE
|
||||||
|
bool
|
||||||
|
prompt "STM32F107x Reset & Clock Control"
|
||||||
|
default y if SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE
|
||||||
|
help
|
||||||
|
Enable driver for Reset & Clock Control subsystem found
|
||||||
|
in STM32F105/STM32F107 family of MCUs
|
||||||
|
|
||||||
|
config CLOCK_CONTROL_STM32F10X_CONN_LINE_DEVICE_INIT_PRIORITY
|
||||||
|
int "Clock Control Device Priority"
|
||||||
|
default 1
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE
|
||||||
|
help
|
||||||
|
This option controls the priority of clock control
|
||||||
|
device initialization. Higher priority ensures that the device
|
||||||
|
is initialized earlier in the startup cycle. If unsure, leave
|
||||||
|
at default value 1
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "STM32F10x Connectivity Line System Clock Source"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_HSI
|
||||||
|
bool "HSI"
|
||||||
|
help
|
||||||
|
Use HSI as source of SYSCLK
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_HSE
|
||||||
|
bool "HSE"
|
||||||
|
help
|
||||||
|
Use HSE as source of SYSCLK
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_PLLCLK
|
||||||
|
bool "PLLCLK"
|
||||||
|
help
|
||||||
|
Use PLLCLK as source of SYSCLK
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "STM32F10x Connectivity Line PLL Clock Source"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_PLLCLK
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PLL_SRC_HSI
|
||||||
|
bool "HSI"
|
||||||
|
help
|
||||||
|
Use HSI divided by 2 as source of PLL
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PLL_SRC_PREDIV1
|
||||||
|
bool "PREDIV1"
|
||||||
|
help
|
||||||
|
Use clock from PREDIV1 as source of PLL
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "STM32F10x Connectivity Line PREDIV1 entry clock source"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && CLOCK_STM32F10X_CONN_LINE_PLL_SRC_PREDIV1
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_HSE
|
||||||
|
bool "HSE"
|
||||||
|
help
|
||||||
|
Use HSE as source of PREDIV1
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_PLL2CLK
|
||||||
|
bool "PLL2CLK"
|
||||||
|
help
|
||||||
|
Use clock from PLL2CLK as source of PLL
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_HSE_BYPASS
|
||||||
|
bool "HSE bypass"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && (CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_HSE || CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_HSE)
|
||||||
|
help
|
||||||
|
Enable this option to bypass external high-speed clock (HSE).
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PREDIV1
|
||||||
|
int "PREDIV1 Prescler"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && CLOCK_STM32F10X_CONN_LINE_PLL_SRC_PREDIV1
|
||||||
|
default 0
|
||||||
|
range 0 16
|
||||||
|
help
|
||||||
|
PREDIV1 is PREDIV1SCR clock signal prescaler, allowed values: 0 - 16.
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER
|
||||||
|
int "PLL multiplier"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_PLLCLK
|
||||||
|
default 9
|
||||||
|
range 4 13
|
||||||
|
help
|
||||||
|
PLL multiplier, allowed values: 4 - 9 and 13 (in fact the multiplication factor is 6.5).
|
||||||
|
Values in range 10-12 are reserved. PLL output must not exceed 72MHz.
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER
|
||||||
|
int "PLL2 multiplier"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_PLL2CLK
|
||||||
|
default 8
|
||||||
|
range 8 20
|
||||||
|
help
|
||||||
|
PLL2 multiplier, allowed values: 8 - 20. PLL2 output must not exceed 72MHz.
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_PREDIV2
|
||||||
|
int "PREDIV2 Prescler"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE && CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_PLL2CLK
|
||||||
|
default 0
|
||||||
|
range 0 16
|
||||||
|
help
|
||||||
|
PREDIV2 is HSE prescaler, allowed values: 0 - 16.
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_AHB_PRESCALER
|
||||||
|
int "AHB prescaler"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE
|
||||||
|
default 0
|
||||||
|
range 0 512
|
||||||
|
help
|
||||||
|
AHB prescaler, allowed values: 0, 2, 4, 8, 16, 64, 128,
|
||||||
|
256, 512.
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_APB1_PRESCALER
|
||||||
|
int "APB1 prescaler"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE
|
||||||
|
default 0
|
||||||
|
range 0 16
|
||||||
|
help
|
||||||
|
APB1 Low speed clock (PCLK1) prescaler, allowed values:
|
||||||
|
0, 2, 4, 8, 16. The APB1 clock must not exceed 36MHz.
|
||||||
|
|
||||||
|
config CLOCK_STM32F10X_CONN_LINE_APB2_PRESCALER
|
||||||
|
int "APB2 prescaler"
|
||||||
|
depends on CLOCK_CONTROL_STM32F10X_CONN_LINE
|
||||||
|
default 0
|
||||||
|
range 0 16
|
||||||
|
help
|
||||||
|
APB2 High speed clock (PCLK2) prescaler, allowed values:
|
||||||
|
0, 2, 4, 8, 16
|
||||||
|
|
||||||
|
endif
|
|
@ -15,12 +15,12 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
if SOC_SERIES_STM32F1X
|
if SOC_STM32F10X_DENSITY_DEVICE
|
||||||
|
|
||||||
menuconfig CLOCK_CONTROL_STM32F10X
|
menuconfig CLOCK_CONTROL_STM32F10X
|
||||||
bool
|
bool
|
||||||
prompt "STM32F10x Reset & Clock Control"
|
prompt "STM32F10x Reset & Clock Control"
|
||||||
default y if SOC_SERIES_STM32F1X
|
default y if SOC_STM32F10X_DENSITY_DEVICE
|
||||||
help
|
help
|
||||||
Enable driver for Reset & Clock Control subsystem found
|
Enable driver for Reset & Clock Control subsystem found
|
||||||
in STM32F1 family of MCUs
|
in STM32F1 family of MCUs
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
obj-$(CONFIG_CLOCK_CONTROL_NRF5) += nrf5_power_clock.o
|
||||||
obj-$(CONFIG_CLOCK_CONTROL_QUARK_SE) += quark_se_clock_control.o
|
obj-$(CONFIG_CLOCK_CONTROL_QUARK_SE) += quark_se_clock_control.o
|
||||||
obj-$(CONFIG_CLOCK_CONTROL_STM32F10X) += stm32f10x_clock.o
|
obj-$(CONFIG_CLOCK_CONTROL_STM32F10X) += stm32f10x_clock.o
|
||||||
|
obj-$(CONFIG_CLOCK_CONTROL_STM32F10X_CONN_LINE) += stm32f107xx_clock.o
|
||||||
obj-$(CONFIG_CLOCK_CONTROL_STM32F4X) += stm32f4x_clock.o
|
obj-$(CONFIG_CLOCK_CONTROL_STM32F4X) += stm32f4x_clock.o
|
||||||
obj-$(CONFIG_CLOCK_CONTROL_NRF5) += nrf5_power_clock.o
|
|
||||||
obj-$(CONFIG_CLOCK_CONTROL_STM32L4X) += stm32l4x_clock.o
|
obj-$(CONFIG_CLOCK_CONTROL_STM32L4X) += stm32l4x_clock.o
|
||||||
obj-$(CONFIG_CLOCK_CONTROL_BEETLE) += beetle_clock_control.o
|
obj-$(CONFIG_CLOCK_CONTROL_BEETLE) += beetle_clock_control.o
|
||||||
|
|
426
drivers/clock_control/stm32f107xx_clock.c
Normal file
426
drivers/clock_control/stm32f107xx_clock.c
Normal file
|
@ -0,0 +1,426 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 RnDity Sp. z o.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Driver for Reset & Clock Control of STM32F10x family processor.
|
||||||
|
*
|
||||||
|
* Based on reference manual:
|
||||||
|
* STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx
|
||||||
|
* advanced ARM ® -based 32-bit MCUs
|
||||||
|
*
|
||||||
|
* Chapter 8: Connectivity line devices: reset and clock control (RCC)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <soc.h>
|
||||||
|
#include <soc_registers.h>
|
||||||
|
#include <clock_control.h>
|
||||||
|
#include <misc/util.h>
|
||||||
|
#include <clock_control/stm32_clock_control.h>
|
||||||
|
|
||||||
|
struct stm32f10x_rcc_data {
|
||||||
|
uint8_t *base;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int stm32f10x_clock_control_on(struct device *dev,
|
||||||
|
clock_control_subsys_t sub_system)
|
||||||
|
{
|
||||||
|
struct stm32f10x_rcc_data *data = dev->driver_data;
|
||||||
|
volatile struct stm32f10x_rcc *rcc =
|
||||||
|
(struct stm32f10x_rcc *)(data->base);
|
||||||
|
uint32_t subsys = POINTER_TO_UINT(sub_system);
|
||||||
|
|
||||||
|
if (subsys > STM32F10X_CLOCK_APB2_BASE) {
|
||||||
|
subsys &= ~(STM32F10X_CLOCK_APB2_BASE);
|
||||||
|
rcc->apb2enr |= subsys;
|
||||||
|
} else {
|
||||||
|
rcc->apb1enr |= subsys;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int stm32f10x_clock_control_off(struct device *dev,
|
||||||
|
clock_control_subsys_t sub_system)
|
||||||
|
{
|
||||||
|
struct stm32f10x_rcc_data *data = dev->driver_data;
|
||||||
|
volatile struct stm32f10x_rcc *rcc =
|
||||||
|
(struct stm32f10x_rcc *)(data->base);
|
||||||
|
uint32_t subsys = POINTER_TO_UINT(sub_system);
|
||||||
|
|
||||||
|
if (subsys > STM32F10X_CLOCK_APB2_BASE) {
|
||||||
|
subsys &= ~(STM32F10X_CLOCK_APB2_BASE);
|
||||||
|
rcc->apb2enr &= ~subsys;
|
||||||
|
} else {
|
||||||
|
rcc->apb1enr &= ~subsys;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief helper for mapping a setting to register value
|
||||||
|
*/
|
||||||
|
struct regval_map {
|
||||||
|
int val;
|
||||||
|
int reg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int map_reg_val(const struct regval_map *map, size_t cnt, int val)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cnt; i++) {
|
||||||
|
if (map[i].val == val) {
|
||||||
|
return map[i].reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief map APB prescaler setting to register value
|
||||||
|
*/
|
||||||
|
static int apb_prescaler(int prescaler)
|
||||||
|
{
|
||||||
|
if (prescaler == 0) {
|
||||||
|
return STM32F10X_RCC_CFG_HCLK_DIV_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct regval_map map[] = {
|
||||||
|
{0, STM32F10X_RCC_CFG_HCLK_DIV_0},
|
||||||
|
{2, STM32F10X_RCC_CFG_HCLK_DIV_2},
|
||||||
|
{4, STM32F10X_RCC_CFG_HCLK_DIV_4},
|
||||||
|
{8, STM32F10X_RCC_CFG_HCLK_DIV_8},
|
||||||
|
{16, STM32F10X_RCC_CFG_HCLK_DIV_16},
|
||||||
|
};
|
||||||
|
|
||||||
|
return map_reg_val(map, ARRAY_SIZE(map), prescaler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief map AHB prescaler setting to register value
|
||||||
|
*/
|
||||||
|
static int ahb_prescaler(int prescaler)
|
||||||
|
{
|
||||||
|
if (prescaler == 0) {
|
||||||
|
return STM32F10X_RCC_CFG_SYSCLK_DIV_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct regval_map map[] = {
|
||||||
|
{0, STM32F10X_RCC_CFG_SYSCLK_DIV_0},
|
||||||
|
{2, STM32F10X_RCC_CFG_SYSCLK_DIV_2},
|
||||||
|
{4, STM32F10X_RCC_CFG_SYSCLK_DIV_4},
|
||||||
|
{8, STM32F10X_RCC_CFG_SYSCLK_DIV_8},
|
||||||
|
{16, STM32F10X_RCC_CFG_SYSCLK_DIV_16},
|
||||||
|
{64, STM32F10X_RCC_CFG_SYSCLK_DIV_64},
|
||||||
|
{128, STM32F10X_RCC_CFG_SYSCLK_DIV_128},
|
||||||
|
{256, STM32F10X_RCC_CFG_SYSCLK_DIV_256},
|
||||||
|
{512, STM32F10X_RCC_CFG_SYSCLK_DIV_512},
|
||||||
|
};
|
||||||
|
|
||||||
|
return map_reg_val(map, ARRAY_SIZE(map), prescaler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief select PREDIV division factor
|
||||||
|
*/
|
||||||
|
static int prediv_prescaler(int prescaler)
|
||||||
|
{
|
||||||
|
if (prescaler == 0) {
|
||||||
|
return STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct regval_map map[] = {
|
||||||
|
{0, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_0},
|
||||||
|
{2, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_2},
|
||||||
|
{3, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_3},
|
||||||
|
{4, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_4},
|
||||||
|
{5, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_5},
|
||||||
|
{6, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_6},
|
||||||
|
{7, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_7},
|
||||||
|
{8, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_8},
|
||||||
|
{9, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_9},
|
||||||
|
{10, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_10},
|
||||||
|
{11, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_11},
|
||||||
|
{12, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_12},
|
||||||
|
{13, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_13},
|
||||||
|
{14, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_14},
|
||||||
|
{15, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_15},
|
||||||
|
{16, STM32F10X_CONN_LINE_RCC_CFGR2_PREDIV_DIV_16},
|
||||||
|
};
|
||||||
|
|
||||||
|
return map_reg_val(map, ARRAY_SIZE(map), prescaler);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER
|
||||||
|
/**
|
||||||
|
* @brief map PLL multiplier setting to register value
|
||||||
|
*/
|
||||||
|
static int pllmul(int mul)
|
||||||
|
{
|
||||||
|
/* x4 -> 0x2
|
||||||
|
* x5 -> 0x3
|
||||||
|
* x6 -> 0x4
|
||||||
|
* x7 -> 0x5
|
||||||
|
* x8 -> 0x6
|
||||||
|
* x9 -> 0x7
|
||||||
|
* x6.5 -> 0xd
|
||||||
|
*/
|
||||||
|
if (mul == 13) {
|
||||||
|
/* ToDo: do something with 6.5 multiplication */
|
||||||
|
return 0xd;
|
||||||
|
} else {
|
||||||
|
return mul - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER */
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER
|
||||||
|
static int pll2mul(int mul)
|
||||||
|
{
|
||||||
|
/* x8 -> 0x6
|
||||||
|
* x9 -> 0x7
|
||||||
|
* x10 -> 0x8
|
||||||
|
* x11 -> 0x9
|
||||||
|
* x12 -> 0xa
|
||||||
|
* x13 -> 0xb
|
||||||
|
* x14 -> 0xc
|
||||||
|
* x16 -> 0xe
|
||||||
|
* x20 -> 0xf
|
||||||
|
*/
|
||||||
|
if (mul == 20) {
|
||||||
|
return 0xf;
|
||||||
|
} else {
|
||||||
|
return mul - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER */
|
||||||
|
|
||||||
|
static uint32_t get_ahb_clock(uint32_t sysclk)
|
||||||
|
{
|
||||||
|
/* AHB clock is generated based on SYSCLK */
|
||||||
|
uint32_t sysclk_div =
|
||||||
|
CONFIG_CLOCK_STM32F10X_CONN_LINE_AHB_PRESCALER;
|
||||||
|
|
||||||
|
if (sysclk_div == 0) {
|
||||||
|
sysclk_div = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sysclk / sysclk_div;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_apb_clock(uint32_t ahb_clock, uint32_t prescaler)
|
||||||
|
{
|
||||||
|
if (prescaler == 0) {
|
||||||
|
prescaler = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ahb_clock / prescaler;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int stm32f10x_clock_control_get_subsys_rate(struct device *clock,
|
||||||
|
clock_control_subsys_t sub_system,
|
||||||
|
uint32_t *rate)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(clock);
|
||||||
|
|
||||||
|
uint32_t subsys = POINTER_TO_UINT(sub_system);
|
||||||
|
uint32_t prescaler =
|
||||||
|
CONFIG_CLOCK_STM32F10X_CONN_LINE_APB1_PRESCALER;
|
||||||
|
/* assumes SYSCLK is SYS_CLOCK_HW_CYCLES_PER_SEC */
|
||||||
|
uint32_t ahb_clock =
|
||||||
|
get_ahb_clock(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
|
||||||
|
|
||||||
|
if (subsys > STM32F10X_CLOCK_APB2_BASE) {
|
||||||
|
prescaler =
|
||||||
|
CONFIG_CLOCK_STM32F10X_CONN_LINE_APB2_PRESCALER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rate = get_apb_clock(ahb_clock, prescaler);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clock_control_driver_api stm32f10x_clock_control_api = {
|
||||||
|
.on = stm32f10x_clock_control_on,
|
||||||
|
.off = stm32f10x_clock_control_off,
|
||||||
|
.get_rate = stm32f10x_clock_control_get_subsys_rate,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setup embedded flash controller
|
||||||
|
*
|
||||||
|
* Configure flash access time latency depending on SYSCLK.
|
||||||
|
*/
|
||||||
|
static inline void setup_flash(void)
|
||||||
|
{
|
||||||
|
volatile struct stm32f10x_flash *flash =
|
||||||
|
(struct stm32f10x_flash *)(FLASH_R_BASE);
|
||||||
|
|
||||||
|
if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= 24000000) {
|
||||||
|
flash->acr.bit.latency = STM32F10X_FLASH_LATENCY_0;
|
||||||
|
} else if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= 48000000) {
|
||||||
|
flash->acr.bit.latency = STM32F10X_FLASH_LATENCY_1;
|
||||||
|
} else if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= 72000000) {
|
||||||
|
flash->acr.bit.latency = STM32F10X_FLASH_LATENCY_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stm32f10x_clock_control_init(struct device *dev)
|
||||||
|
{
|
||||||
|
struct stm32f10x_rcc_data *data = dev->driver_data;
|
||||||
|
volatile struct stm32f10x_rcc *rcc =
|
||||||
|
(struct stm32f10x_rcc *)(data->base);
|
||||||
|
/* SYSCLK source defaults to HSI */
|
||||||
|
int sysclk_src = STM32F10X_RCC_CFG_SYSCLK_SRC_HSI;
|
||||||
|
uint32_t hpre =
|
||||||
|
ahb_prescaler(CONFIG_CLOCK_STM32F10X_CONN_LINE_AHB_PRESCALER);
|
||||||
|
uint32_t ppre1 =
|
||||||
|
apb_prescaler(CONFIG_CLOCK_STM32F10X_CONN_LINE_APB1_PRESCALER);
|
||||||
|
uint32_t ppre2 =
|
||||||
|
apb_prescaler(CONFIG_CLOCK_STM32F10X_CONN_LINE_APB2_PRESCALER);
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER
|
||||||
|
uint32_t pll_mul =
|
||||||
|
pllmul(CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER);
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER */
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER
|
||||||
|
uint32_t pll2mul =
|
||||||
|
pllmul(CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER);
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER */
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1
|
||||||
|
uint32_t prediv1 =
|
||||||
|
prediv_prescaler(CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1);
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1 */
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV2
|
||||||
|
uint32_t prediv2 =
|
||||||
|
prediv_prescaler(CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV2);
|
||||||
|
#endif /* CLOCK_STM32F10X_CONN_LINE_PREDIV2 */
|
||||||
|
|
||||||
|
/* disable PLLs */
|
||||||
|
rcc->cr.bit.pllon = 0;
|
||||||
|
rcc->cr.bit.pll2on = 0;
|
||||||
|
rcc->cr.bit.pll3on = 0;
|
||||||
|
/* disable HSE */
|
||||||
|
rcc->cr.bit.hseon = 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_HSE_BYPASS
|
||||||
|
/* HSE is disabled, HSE bypass can be enabled*/
|
||||||
|
rcc->cr.bit.hsebyp = 1;
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_HSE_BYPASS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_SRC_HSI
|
||||||
|
/* enable HSI clock */
|
||||||
|
rcc->cr.bit.hsion = 1;
|
||||||
|
/* this should end after one test */
|
||||||
|
while (rcc->cr.bit.hsirdy != 1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HSI oscillator clock / 2 selected as PLL input clock */
|
||||||
|
rcc->cfgr.bit.pllsrc = STM32F10X_RCC_CFG_PLL_SRC_HSI;
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_PLL_SRC_HSI */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_SRC_PREDIV1
|
||||||
|
|
||||||
|
/* wait for to become ready */
|
||||||
|
rcc->cr.bit.hseon = 1;
|
||||||
|
while (rcc->cr.bit.hserdy != 1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
rcc->cfgr2.bit.prediv1 = prediv1;
|
||||||
|
|
||||||
|
/* Clock from PREDIV1 selected as PLL input clock */
|
||||||
|
rcc->cfgr.bit.pllsrc = STM32F10X_RCC_CFG_PLL_SRC_PREDIV1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_HSE
|
||||||
|
/* HSE oscillator clock selected as PREDIV1 clock entry */
|
||||||
|
rcc->cfgr2.bit.prediv1src = STM32F10X_RCC_CFG2_PREDIV1_SRC_HSE;
|
||||||
|
#else
|
||||||
|
/* PLL2 selected as PREDIV1 clock entry */
|
||||||
|
rcc->cfgr2.bit.prediv1src = STM32F10X_RCC_CFG2_PREDIV1_SRC_PLL2;
|
||||||
|
|
||||||
|
rcc->cfgr2.bit.prediv2 = prediv2;
|
||||||
|
rcc->cfgr2.bit.pll2mul = pll2mul;
|
||||||
|
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_HSE */
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_SRC_PREDIV1 */
|
||||||
|
|
||||||
|
/* setup AHB prescaler */
|
||||||
|
rcc->cfgr.bit.hpre = hpre;
|
||||||
|
|
||||||
|
/* setup APB1, must not exceed 36MHz */
|
||||||
|
rcc->cfgr.bit.ppre1 = ppre1;
|
||||||
|
|
||||||
|
/* setup APB2 */
|
||||||
|
rcc->cfgr.bit.ppre2 = ppre2;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_HSI
|
||||||
|
/* enable HSI clock */
|
||||||
|
rcc->cr.bit.hsion = 1;
|
||||||
|
/* this should end after one test */
|
||||||
|
while (rcc->cr.bit.hsirdy != 1) {
|
||||||
|
}
|
||||||
|
sysclk_src = STM32F10X_RCC_CFG_SYSCLK_SRC_HSI;
|
||||||
|
#elif defined(CONFIG_CLOCK_STM32F10X_SYSCLK_SRC_HSE)
|
||||||
|
/* enable HSE clock */
|
||||||
|
rcc->cr.bit.hseon = 1;
|
||||||
|
/* wait for to become ready */
|
||||||
|
while (rcc->cr.bit.hserdy != 1) {
|
||||||
|
}
|
||||||
|
sysclk_src = STM32F10X_RCC_CFG_SYSCLK_SRC_HSE;
|
||||||
|
#elif defined(CONFIG_CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_PLLCLK)
|
||||||
|
/* setup PLL multiplication (PLL must be disabled) */
|
||||||
|
rcc->cfgr.bit.pllmul = pll_mul;
|
||||||
|
|
||||||
|
/* enable PLL */
|
||||||
|
rcc->cr.bit.pllon = 1;
|
||||||
|
|
||||||
|
/* wait for PLL to become ready */
|
||||||
|
while (rcc->cr.bit.pllrdy != 1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
sysclk_src = STM32F10X_RCC_CFG_SYSCLK_SRC_PLL;
|
||||||
|
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_SYSCLK_SRC_HSI */
|
||||||
|
|
||||||
|
/* configure flash access latency before SYSCLK source
|
||||||
|
* switch
|
||||||
|
*/
|
||||||
|
setup_flash();
|
||||||
|
|
||||||
|
/* set SYSCLK clock value */
|
||||||
|
rcc->cfgr.bit.sw = sysclk_src;
|
||||||
|
|
||||||
|
/* wait for SYSCLK to switch the source */
|
||||||
|
while (rcc->cfgr.bit.sws != sysclk_src) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct stm32f10x_rcc_data stm32f10x_rcc_data = {
|
||||||
|
.base = (uint8_t *)RCC_BASE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: move prescaler/multiplier defines into device config */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RCC device, note that priority is intentionally set to 1 so
|
||||||
|
* that the device init runs just after SOC init
|
||||||
|
*/
|
||||||
|
DEVICE_AND_API_INIT(rcc_stm32f10x, STM32_CLOCK_CONTROL_NAME,
|
||||||
|
&stm32f10x_clock_control_init,
|
||||||
|
&stm32f10x_rcc_data, NULL,
|
||||||
|
PRE_KERNEL_1,
|
||||||
|
CONFIG_CLOCK_CONTROL_STM32F10X_CONN_LINE_DEVICE_INIT_PRIORITY,
|
||||||
|
&stm32f10x_clock_control_api);
|
|
@ -26,9 +26,7 @@
|
||||||
#include "stm32f1_clock_control.h"
|
#include "stm32f1_clock_control.h"
|
||||||
#elif CONFIG_SOC_SERIES_STM32F4X
|
#elif CONFIG_SOC_SERIES_STM32F4X
|
||||||
#include "stm32f4_clock_control.h"
|
#include "stm32f4_clock_control.h"
|
||||||
#endif
|
#elif CONFIG_SOC_SERIES_STM32L4X
|
||||||
|
|
||||||
#ifdef CONFIG_SOC_SERIES_STM32L4X
|
|
||||||
#include "stm32l4x_clock_control.h"
|
#include "stm32l4x_clock_control.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue