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:
Adam Podogrocki 2016-10-28 12:46:50 +02:00 committed by Kumar Gala
commit 72782f542c
7 changed files with 653 additions and 8 deletions

View file

@ -1,5 +1,6 @@
/*
* 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");
* 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
* clock control
* Chapter 8: Connectivity line devices: reset and clock control (RCC)
*/
/* 8.3.1 Clock control register (RCC_CR) */
#ifdef CONFIG_SOC_STM32F10X_DENSITY_DEVICE
enum {
STM32F10X_RCC_CFG_PLL_SRC_HSI = 0x0,
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_2 = 0x1,
};
#endif
enum {
STM32F10X_RCC_CFG_SYSCLK_SRC_HSI = 0x0,
@ -65,6 +69,37 @@ enum {
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
*/
@ -84,7 +119,15 @@ union __rcc_cr {
uint32_t rsvd__20_23 :4 __packed;
uint32_t pllon :1 __packed;
uint32_t pllrdy :1 __packed;
#if CONFIG_SOC_STM32F10X_DENSITY_DEVICE
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;
};
@ -107,6 +150,20 @@ union __rcc_cfgr {
} 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 {
union __rcc_cr cr;
union __rcc_cfgr cfgr;
@ -118,6 +175,10 @@ struct stm32f10x_rcc {
uint32_t apb1enr;
uint32_t bdcr;
uint32_t csr;
#ifdef CONFIG_SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE
uint32_t ahbrstr;
union __rcc_cfgr2 cfgr2;
#endif
};
#endif /* _STM32F10X_CLOCK_H_ */

View file

@ -50,13 +50,15 @@ config SYS_LOG_CLOCK_CONTROL_LEVEL
- 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.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"

View 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

View file

@ -15,12 +15,12 @@
# limitations under the License.
#
if SOC_SERIES_STM32F1X
if SOC_STM32F10X_DENSITY_DEVICE
menuconfig CLOCK_CONTROL_STM32F10X
bool
prompt "STM32F10x Reset & Clock Control"
default y if SOC_SERIES_STM32F1X
default y if SOC_STM32F10X_DENSITY_DEVICE
help
Enable driver for Reset & Clock Control subsystem found
in STM32F1 family of MCUs

View file

@ -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_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_NRF5) += nrf5_power_clock.o
obj-$(CONFIG_CLOCK_CONTROL_STM32L4X) += stm32l4x_clock.o
obj-$(CONFIG_CLOCK_CONTROL_BEETLE) += beetle_clock_control.o

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

View file

@ -26,9 +26,7 @@
#include "stm32f1_clock_control.h"
#elif CONFIG_SOC_SERIES_STM32F4X
#include "stm32f4_clock_control.h"
#endif
#ifdef CONFIG_SOC_SERIES_STM32L4X
#elif CONFIG_SOC_SERIES_STM32L4X
#include "stm32l4x_clock_control.h"
#endif