clock/stm32: add STM32F3X reset and clock control
Change-Id: Ie5f3ffec0b3aaf15f9d9f8063d2bab6be5aebb6e Signed-off-by: Adam Podogrocki <adam.podogrocki@rndity.com>
This commit is contained in:
parent
42a4615973
commit
c514f671c7
8 changed files with 734 additions and 0 deletions
70
arch/arm/soc/st_stm32/stm32f3/flash_registers.h
Normal file
70
arch/arm/soc/st_stm32/stm32f3/flash_registers.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _STM32F3X_FLASH_REGISTERS_H_
|
||||
#define _STM32F3X_FLASH_REGISTERS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Based on reference manual:
|
||||
* STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx
|
||||
* advanced ARM ® -based 32-bit MCUs
|
||||
* &
|
||||
* STM32F334xx advanced ARM ® -based 32-bit MCUs
|
||||
*
|
||||
* Chapter 3.3.3: Embedded Flash Memory
|
||||
*/
|
||||
|
||||
enum {
|
||||
STM32_FLASH_LATENCY_0 = 0x0,
|
||||
STM32_FLASH_LATENCY_1 = 0x1,
|
||||
STM32_FLASH_LATENCY_2 = 0x2,
|
||||
};
|
||||
|
||||
/* 3.3.3 FLASH_ACR */
|
||||
union ef_acr {
|
||||
uint32_t val;
|
||||
struct {
|
||||
uint32_t latency :3 __packed;
|
||||
uint32_t hlfcya :1 __packed;
|
||||
uint32_t prftbe :1 __packed;
|
||||
uint32_t prftbs :1 __packed;
|
||||
uint32_t rsvd__6_31 :26 __packed;
|
||||
} bit;
|
||||
};
|
||||
|
||||
/* 3.3.3 Embedded flash registers */
|
||||
struct stm32_flash {
|
||||
union ef_acr acr;
|
||||
uint32_t keyr;
|
||||
uint32_t optkeyr;
|
||||
uint32_t sr;
|
||||
uint32_t cr;
|
||||
uint32_t ar;
|
||||
uint32_t rsvd;
|
||||
uint32_t obr;
|
||||
uint32_t wrpr;
|
||||
};
|
||||
|
||||
/* list of device commands */
|
||||
enum stm32_embedded_flash_cmd {
|
||||
STM32_FLASH_CMD_LATENCY_FOR_CLOCK_SET,
|
||||
};
|
||||
|
||||
#endif /* _STM32F3X_FLASH_REGISTERS_H_ */
|
|
@ -19,5 +19,6 @@
|
|||
|
||||
/* include register mapping headers */
|
||||
#include "rcc_registers.h"
|
||||
#include "flash_registers.h"
|
||||
|
||||
#endif /* _STM32F3X_SOC_REGISTERS_H_ */
|
||||
|
|
|
@ -48,6 +48,8 @@ source "drivers/clock_control/Kconfig.stm32f10x"
|
|||
|
||||
source "drivers/clock_control/Kconfig.stm32f107xx"
|
||||
|
||||
source "drivers/clock_control/Kconfig.stm32f3x"
|
||||
|
||||
source "drivers/clock_control/Kconfig.stm32f4x"
|
||||
|
||||
source "drivers/clock_control/Kconfig.stm32l4x"
|
||||
|
|
125
drivers/clock_control/Kconfig.stm32f3x
Normal file
125
drivers/clock_control/Kconfig.stm32f3x
Normal file
|
@ -0,0 +1,125 @@
|
|||
# Kconfig - STM32F3 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_SERIES_STM32F3X
|
||||
|
||||
menuconfig CLOCK_CONTROL_STM32F3X
|
||||
bool
|
||||
prompt "STM32F3x Reset & Clock Control"
|
||||
depends on CLOCK_CONTROL && SOC_SERIES_STM32F3X
|
||||
default y if SOC_SERIES_STM32F3X
|
||||
help
|
||||
Enable driver for Reset & Clock Control subsystem found
|
||||
in STM32F3 family of MCUs
|
||||
|
||||
config CLOCK_CONTROL_STM32F3X_DEVICE_INIT_PRIORITY
|
||||
int "Clock Control Device Priority"
|
||||
default 1
|
||||
depends on CLOCK_CONTROL_STM32F3X
|
||||
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 "STM32F3x System Clock Source"
|
||||
depends on CLOCK_CONTROL_STM32F3X
|
||||
|
||||
config CLOCK_STM32F3X_SYSCLK_SRC_HSI
|
||||
bool "HSI"
|
||||
help
|
||||
Use HSI as source of SYSCLK
|
||||
|
||||
config CLOCK_STM32F3X_SYSCLK_SRC_HSE
|
||||
bool "HSE"
|
||||
help
|
||||
Use HSE as source of SYSCLK
|
||||
|
||||
config CLOCK_STM32F3X_SYSCLK_SRC_PLL
|
||||
bool "PLL"
|
||||
help
|
||||
Use PLL as source of SYSCLK
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "STM32F3x PLL Clock Source"
|
||||
depends on CLOCK_CONTROL_STM32F3X && CLOCK_STM32F3X_SYSCLK_SRC_PLL
|
||||
|
||||
config CLOCK_STM32F3X_PLL_SRC_HSI
|
||||
bool "HSI"
|
||||
help
|
||||
Use HSI/2 as source of PLL
|
||||
|
||||
config CLOCK_STM32F3X_PLL_SRC_HSE
|
||||
bool "HSE"
|
||||
help
|
||||
Use HSE as source of PLL
|
||||
|
||||
endchoice
|
||||
|
||||
config CLOCK_STM32F3X_HSE_BYPASS
|
||||
bool "HSE bypass"
|
||||
depends on CLOCK_CONTROL_STM32F3X && (CLOCK_STM32F3X_PLL_SRC_HSE || CLOCK_STM32F3X_SYSCLK_SRC_HSE)
|
||||
help
|
||||
Enable this option to bypass external high-speed clock (HSE).
|
||||
|
||||
config CLOCK_STM32F3X_PLL_PREDIV
|
||||
int "PREDIV1 Prescler"
|
||||
depends on CLOCK_CONTROL_STM32F3X && CLOCK_STM32F3X_PLL_SRC_HSE
|
||||
default 0
|
||||
range 0 16
|
||||
help
|
||||
PREDIV is PLLSCR clock signal prescaler, allowed values: 0 - 16.
|
||||
|
||||
config CLOCK_STM32F3X_PLL_MULTIPLIER
|
||||
int "PLL multiplier"
|
||||
depends on CLOCK_CONTROL_STM32F3X && CLOCK_STM32F3X_SYSCLK_SRC_PLL
|
||||
default 9
|
||||
range 2 16
|
||||
help
|
||||
PLL multiplier, allowed values: 2-16. PLL output must not exceed 72MHz.
|
||||
|
||||
config CLOCK_STM32F3X_AHB_PRESCALER
|
||||
int "AHB prescaler"
|
||||
depends on CLOCK_CONTROL_STM32F3X
|
||||
default 0
|
||||
range 0 512
|
||||
help
|
||||
AHB prescaler, allowed values: 0, 2, 4, 8, 16, 64, 128,
|
||||
256, 512.
|
||||
|
||||
config CLOCK_STM32F3X_APB1_PRESCALER
|
||||
int "APB1 prescaler"
|
||||
depends on CLOCK_CONTROL_STM32F3X
|
||||
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_STM32F3X_APB2_PRESCALER
|
||||
int "APB2 prescaler"
|
||||
depends on CLOCK_CONTROL_STM32F3X
|
||||
default 0
|
||||
range 0 16
|
||||
help
|
||||
APB2 High speed clock (PCLK2) prescaler, allowed values:
|
||||
0, 2, 4, 8, 16
|
||||
|
||||
endif
|
|
@ -2,6 +2,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_STM32F3X) += stm32f3x_clock.o
|
||||
obj-$(CONFIG_CLOCK_CONTROL_STM32F4X) += stm32f4x_clock.o
|
||||
obj-$(CONFIG_CLOCK_CONTROL_STM32L4X) += stm32l4x_clock.o
|
||||
obj-$(CONFIG_CLOCK_CONTROL_BEETLE) += beetle_clock_control.o
|
||||
|
|
408
drivers/clock_control/stm32f3x_clock.c
Normal file
408
drivers/clock_control/stm32f3x_clock.c
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* 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 STM32F3x family processor.
|
||||
*
|
||||
* Based on reference manual:
|
||||
* STM32F303xB.C.D.E advanced ARM-based 32-bit MCU
|
||||
* advanced ARM ® -based 32-bit MCUs
|
||||
*
|
||||
* Chapter 9: Reset and clock control (RCC)
|
||||
*
|
||||
* STM32F334xx advanced ARM ® -based 32-bit MCUs
|
||||
*
|
||||
* Chapter 8: Reset and clock control (RCC)
|
||||
*/
|
||||
|
||||
#include <soc.h>
|
||||
#include <soc_registers.h>
|
||||
#include <clock_control.h>
|
||||
#include <misc/util.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <clock_control/stm32_clock_control.h>
|
||||
|
||||
struct stm32f3x_rcc_data {
|
||||
uint8_t *base;
|
||||
};
|
||||
|
||||
static int stm32f3x_clock_control_on(struct device *dev,
|
||||
clock_control_subsys_t sub_system)
|
||||
{
|
||||
struct stm32f3x_rcc_data *data = dev->driver_data;
|
||||
|
||||
volatile struct stm32f3x_rcc *rcc =
|
||||
(struct stm32f3x_rcc *)(data->base);
|
||||
uint32_t subsys = POINTER_TO_UINT(sub_system);
|
||||
|
||||
if (subsys > STM32F3X_CLOCK_AHB_BASE) {
|
||||
subsys &= ~(STM32F3X_CLOCK_AHB_BASE);
|
||||
rcc->ahbenr |= subsys;
|
||||
} else if (subsys > STM32F3X_CLOCK_APB2_BASE) {
|
||||
subsys &= ~(STM32F3X_CLOCK_APB2_BASE);
|
||||
rcc->apb2enr |= subsys;
|
||||
} else {
|
||||
rcc->apb1enr |= subsys;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32f3x_clock_control_off(struct device *dev,
|
||||
clock_control_subsys_t sub_system)
|
||||
{
|
||||
struct stm32f3x_rcc_data *data = dev->driver_data;
|
||||
|
||||
volatile struct stm32f3x_rcc *rcc =
|
||||
(struct stm32f3x_rcc *)(data->base);
|
||||
uint32_t subsys = POINTER_TO_UINT(sub_system);
|
||||
|
||||
if (subsys > STM32F3X_CLOCK_AHB_BASE) {
|
||||
subsys &= ~(STM32F3X_CLOCK_AHB_BASE);
|
||||
rcc->ahbenr &= ~subsys;
|
||||
} else if (subsys > STM32F3X_CLOCK_APB2_BASE) {
|
||||
subsys &= ~(STM32F3X_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, uint8_t normalize)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (map[i].val == val) {
|
||||
return (map[i].reg >> normalize);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief map APB prescaler setting to register value
|
||||
*/
|
||||
static int apb_prescaler(int prescaler)
|
||||
{
|
||||
if (prescaler == 0) {
|
||||
return RCC_HCLK_DIV1;
|
||||
}
|
||||
|
||||
const struct regval_map map[] = {
|
||||
{0, RCC_HCLK_DIV1},
|
||||
{2, RCC_HCLK_DIV2},
|
||||
{4, RCC_HCLK_DIV4},
|
||||
{8, RCC_HCLK_DIV8},
|
||||
{16, RCC_HCLK_DIV16},
|
||||
};
|
||||
|
||||
return map_reg_val(map, ARRAY_SIZE(map),
|
||||
prescaler, RCC_CFGR_PPRE1_Pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief map AHB prescaler setting to register value
|
||||
*/
|
||||
static int ahb_prescaler(int prescaler)
|
||||
{
|
||||
if (prescaler == 0) {
|
||||
return RCC_SYSCLK_DIV1;
|
||||
}
|
||||
|
||||
const struct regval_map map[] = {
|
||||
{0, RCC_SYSCLK_DIV1},
|
||||
{2, RCC_SYSCLK_DIV2},
|
||||
{4, RCC_SYSCLK_DIV4},
|
||||
{8, RCC_SYSCLK_DIV8},
|
||||
{16, RCC_SYSCLK_DIV16},
|
||||
{64, RCC_SYSCLK_DIV64},
|
||||
{128, RCC_SYSCLK_DIV128},
|
||||
{256, RCC_SYSCLK_DIV256},
|
||||
{512, RCC_SYSCLK_DIV512},
|
||||
};
|
||||
|
||||
return map_reg_val(map, ARRAY_SIZE(map),
|
||||
prescaler, RCC_CFGR_HPRE_Pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief map PLL multiplier setting to register value
|
||||
*/
|
||||
static int pllmul(int mul)
|
||||
{
|
||||
/* x2 -> 0x0
|
||||
* x3 -> 0x1
|
||||
* x4 -> 0x2
|
||||
* ...
|
||||
* x15 -> 0xd
|
||||
* x16 -> 0xe
|
||||
* x16 -> 0xf
|
||||
*/
|
||||
return mul - 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief select PREDIV division factor
|
||||
*/
|
||||
static int prediv_prescaler(int prescaler)
|
||||
{
|
||||
if (prescaler == 0) {
|
||||
return RCC_HSE_PREDIV_DIV1;
|
||||
}
|
||||
|
||||
const struct regval_map map[] = {
|
||||
{0, RCC_HSE_PREDIV_DIV1},
|
||||
{2, RCC_HSE_PREDIV_DIV2},
|
||||
{3, RCC_HSE_PREDIV_DIV3},
|
||||
{4, RCC_HSE_PREDIV_DIV4},
|
||||
{5, RCC_HSE_PREDIV_DIV5},
|
||||
{6, RCC_HSE_PREDIV_DIV6},
|
||||
{7, RCC_HSE_PREDIV_DIV7},
|
||||
{8, RCC_HSE_PREDIV_DIV8},
|
||||
{9, RCC_HSE_PREDIV_DIV9},
|
||||
{10, RCC_HSE_PREDIV_DIV10},
|
||||
{11, RCC_HSE_PREDIV_DIV11},
|
||||
{12, RCC_HSE_PREDIV_DIV12},
|
||||
{13, RCC_HSE_PREDIV_DIV13},
|
||||
{14, RCC_HSE_PREDIV_DIV14},
|
||||
{15, RCC_HSE_PREDIV_DIV15},
|
||||
{16, RCC_HSE_PREDIV_DIV16},
|
||||
};
|
||||
|
||||
return map_reg_val(map, ARRAY_SIZE(map), prescaler, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief select System Clock Source
|
||||
*/
|
||||
static int system_clock(int source)
|
||||
{
|
||||
__ASSERT_NO_MSG(IS_RCC_SYSCLKSOURCE(source));
|
||||
return (source >> RCC_CFGR_SW_Pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief select PLL Clock Source
|
||||
*/
|
||||
static int pll_source(int source)
|
||||
{
|
||||
__ASSERT_NO_MSG(IS_RCC_PLLSOURCE(source));
|
||||
return (source >> RCC_CFGR_PLLSRC_Pos);
|
||||
}
|
||||
|
||||
static uint32_t get_ahb_clock(uint32_t sysclk)
|
||||
{
|
||||
/* AHB clock is generated based on SYSCLK */
|
||||
uint32_t sysclk_div = CONFIG_CLOCK_STM32F3X_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 stm32f3x_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_STM32F3X_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 > STM32F3X_CLOCK_AHB_BASE) {
|
||||
prescaler = CONFIG_CLOCK_STM32F3X_AHB_PRESCALER;
|
||||
} else if (subsys > STM32F3X_CLOCK_APB2_BASE) {
|
||||
prescaler = CONFIG_CLOCK_STM32F3X_APB2_PRESCALER;
|
||||
}
|
||||
|
||||
*rate = get_apb_clock(ahb_clock, prescaler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clock_control_driver_api stm32f3x_clock_control_api = {
|
||||
.on = stm32f3x_clock_control_on,
|
||||
.off = stm32f3x_clock_control_off,
|
||||
.get_rate = stm32f3x_clock_control_get_subsys_rate,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief setup embedded flash controller
|
||||
*
|
||||
* Configure flash access time latency depending on SYSCLK.
|
||||
*/
|
||||
static void setup_flash(void)
|
||||
{
|
||||
volatile struct stm32_flash *flash =
|
||||
(struct stm32_flash *)(FLASH_R_BASE);
|
||||
|
||||
if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= 24000000) {
|
||||
flash->acr.bit.latency = STM32_FLASH_LATENCY_0;
|
||||
} else if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= 48000000) {
|
||||
flash->acr.bit.latency = STM32_FLASH_LATENCY_1;
|
||||
} else if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC <= 72000000) {
|
||||
flash->acr.bit.latency = STM32_FLASH_LATENCY_2;
|
||||
}
|
||||
}
|
||||
|
||||
static int stm32f3x_clock_control_init(struct device *dev)
|
||||
{
|
||||
struct stm32f3x_rcc_data *data = dev->driver_data;
|
||||
volatile struct stm32f3x_rcc *rcc =
|
||||
(struct stm32f3x_rcc *)(data->base);
|
||||
/* SYSCLK source defaults to HSI */
|
||||
int sysclk_src = system_clock(RCC_SYSCLKSOURCE_HSI);
|
||||
uint32_t hpre = ahb_prescaler(CONFIG_CLOCK_STM32F3X_AHB_PRESCALER);
|
||||
uint32_t ppre1 = apb_prescaler(CONFIG_CLOCK_STM32F3X_APB1_PRESCALER);
|
||||
uint32_t ppre2 = apb_prescaler(CONFIG_CLOCK_STM32F3X_APB2_PRESCALER);
|
||||
#ifdef CONFIG_CLOCK_STM32F3X_PLL_MULTIPLIER
|
||||
uint32_t pll_mul = pllmul(CONFIG_CLOCK_STM32F3X_PLL_MULTIPLIER);
|
||||
#endif /* CONFIG_CLOCK_STM32F3X_PLL_MULTIPLIER */
|
||||
#ifdef CONFIG_CLOCK_STM32F3X_PLL_PREDIV
|
||||
uint32_t prediv =
|
||||
prediv_prescaler(CONFIG_CLOCK_STM32F3X_PLL_PREDIV);
|
||||
#endif /* CONFIG_CLOCK_STM32F3X_PLL_PREDIV */
|
||||
|
||||
/* disable PLL */
|
||||
rcc->cr.bit.pllon = 0;
|
||||
/* disable HSE */
|
||||
rcc->cr.bit.hseon = 0;
|
||||
|
||||
#ifdef CONFIG_CLOCK_STM32F3X_HSE_BYPASS
|
||||
/* HSE is disabled, HSE bypass can be enabled*/
|
||||
rcc->cr.bit.hsebyp = 1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLOCK_STM32F3X_PLL_SRC_HSI
|
||||
/* enable HSI clock */
|
||||
rcc->cr.bit.hsion = 1;
|
||||
/* this should end after one test */
|
||||
while (rcc->cr.bit.hsirdy != 1) {
|
||||
}
|
||||
|
||||
/* HSI clock divided by 2 selected as PLL entry clock source. */
|
||||
rcc->cfgr.bit.pllsrc = pll_source(RCC_PLLSOURCE_HSI);
|
||||
#endif /* CONFIG_CLOCK_STM32F3X_PLL_SRC_HSI */
|
||||
|
||||
#ifdef CONFIG_CLOCK_STM32F3X_PLL_SRC_HSE
|
||||
|
||||
/* wait for to become ready */
|
||||
rcc->cr.bit.hseon = 1;
|
||||
while (rcc->cr.bit.hserdy != 1) {
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLOCK_STM32F3X_PLL_PREDIV
|
||||
rcc->cfgr2.bit.prediv = prediv;
|
||||
#endif /* CONFIG_CLOCK_STM32F3X_PLL_PREDIV */
|
||||
/* HSE clock selected as PLL entry clock source. */
|
||||
rcc->cfgr.bit.pllsrc = pll_source(RCC_PLLSOURCE_HSE);
|
||||
#endif /* CONFIG_CLOCK_STM32F3X_PLL_SRC_HSE */
|
||||
|
||||
/* 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_STM32F3X_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 = system_clock(RCC_SYSCLKSOURCE_HSI);
|
||||
#elif defined(CONFIG_CLOCK_STM32F3X_SYSCLK_SRC_PLL)
|
||||
/* 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 = system_clock(RCC_SYSCLKSOURCE_PLLCLK);
|
||||
#elif defined(CONFIG_CLOCK_STM32F3X_SYSCLK_SRC_HSE)
|
||||
/* wait for to become ready */
|
||||
rcc->cr.bit.hseon = 1;
|
||||
while (rcc->cr.bit.hserdy != 1) {
|
||||
}
|
||||
|
||||
sysclk_src = system_clock(RCC_SYSCLKSOURCE_HSE);
|
||||
#endif
|
||||
|
||||
/* 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) {
|
||||
}
|
||||
|
||||
dev->driver_api = &stm32f3x_clock_control_api;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct stm32f3x_rcc_data stm32f3x_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_INIT(rcc_stm32f3x, STM32_CLOCK_CONTROL_NAME,
|
||||
&stm32f3x_clock_control_init,
|
||||
&stm32f3x_rcc_data, NULL,
|
||||
PRE_KERNEL_1,
|
||||
CONFIG_CLOCK_CONTROL_STM32F3X_DEVICE_INIT_PRIORITY);
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
||||
* Copyright (c) 2016 BayLibre, SAS
|
||||
* Copyright (c) 2016 RnDity Sp. z o.o.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -14,6 +15,8 @@
|
|||
|
||||
#ifdef CONFIG_SOC_SERIES_STM32F1X
|
||||
#include "stm32f1_clock_control.h"
|
||||
#elif CONFIG_SOC_SERIES_STM32F3X
|
||||
#include "stm32f3_clock_control.h"
|
||||
#elif CONFIG_SOC_SERIES_STM32F4X
|
||||
#include "stm32f4_clock_control.h"
|
||||
#elif CONFIG_SOC_SERIES_STM32L4X
|
||||
|
|
124
include/drivers/clock_control/stm32f3_clock_control.h
Normal file
124
include/drivers/clock_control/stm32f3_clock_control.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _STM32F3_CLOCK_CONTROL_H_
|
||||
#define _STM32F3_CLOCK_CONTROL_H_
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Clock subsystem IDs for STM32F3 family
|
||||
*/
|
||||
|
||||
/* APB1 */
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM2 (1 << 0)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM3 (1 << 1)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM4 (1 << 2)
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_STM32F373XC
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM5 (1 << 3)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM6 (1 << 4)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM7 (1 << 5)
|
||||
#ifdef CONFIG_SOC_STM32F373XC
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM12 (1 << 6)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM13 (1 << 7)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM14 (1 << 8)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM18 (1 << 9)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_WWDG (1 << 11)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_SPI2 (1 << 14)
|
||||
#define STM32F3X_CLOCK_SUBSYS_SPI3 (1 << 15)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_USART2 (1 << 17)
|
||||
#define STM32F3X_CLOCK_SUBSYS_USART3 (1 << 18)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_UART4 (1 << 19)
|
||||
#define STM32F3X_CLOCK_SUBSYS_UART5 (1 << 20)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_I2C1 (1 << 21)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_I2C2 (1 << 22)
|
||||
#define STM32F3X_CLOCK_SUBSYS_USB (1 << 23)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_CAN (1 << 25)
|
||||
#define STM32F3X_CLOCK_SUBSYS_DAC2 (1 << 26)
|
||||
#define STM32F3X_CLOCK_SUBSYS_PWR (1 << 28)
|
||||
#define STM32F3X_CLOCK_SUBSYS_DAC1 (1 << 29)
|
||||
|
||||
#define STM32F3X_CLOCK_APB2_BASE (1 << 30)
|
||||
|
||||
/* APB2 */
|
||||
#define STM32F3X_CLOCK_SUBSYS_SYSCFG (STM32F3X_CLOCK_APB2_BASE | 1 << 0)
|
||||
#ifndef CONFIG_SOC_STM32F373XC
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM1 (STM32F3X_CLOCK_APB2_BASE | 1 << 11)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_SPI1 (STM32F3X_CLOCK_APB2_BASE | 1 << 12)
|
||||
#ifdef CONFIG_SOC_STM32F303XC
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM8 (STM32F3X_CLOCK_APB2_BASE | 1 << 13)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_USART1 (STM32F3X_CLOCK_APB2_BASE | 1 << 14)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_SPI4 (STM32F3X_CLOCK_APB2_BASE | 1 << 15)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM15 (STM32F3X_CLOCK_APB2_BASE | 1 << 16)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM16 (STM32F3X_CLOCK_APB2_BASE | 1 << 17)
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM17 (STM32F3X_CLOCK_APB2_BASE | 1 << 18)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM19 (STM32F3X_CLOCK_APB2_BASE | 1 << 19)
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_STM32F303XC
|
||||
#define STM32F3X_CLOCK_SUBSYS_TIM20 (STM32F3X_CLOCK_APB2_BASE | 1 << 20)
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_HRTIMER1 (STM32F3X_CLOCK_APB2_BASE | 1 << 29)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_AHB_BASE (1 << 31)
|
||||
|
||||
/* AHB */
|
||||
#define STM32F3X_CLOCK_SUBSYS_DMA1 (STM32F3X_CLOCK_AHB_BASE | 1 << 0)
|
||||
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_DMA2 (STM32F3X_CLOCK_AHB_BASE | 1 << 1)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_SRAM (STM32F3X_CLOCK_AHB_BASE | 1 << 2)
|
||||
#define STM32F3X_CLOCK_SUBSYS_FLITF (STM32F3X_CLOCK_AHB_BASE | 1 << 4)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_FMC (STM32F3X_CLOCK_AHB_BASE | 1 << 5)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_CRC (STM32F3X_CLOCK_AHB_BASE | 1 << 6)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPH (STM32F3X_CLOCK_AHB_BASE | 1 << 16)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPA (STM32F3X_CLOCK_AHB_BASE | 1 << 17)
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPB (STM32F3X_CLOCK_AHB_BASE | 1 << 18)
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPC (STM32F3X_CLOCK_AHB_BASE | 1 << 19)
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPD (STM32F3X_CLOCK_AHB_BASE | 1 << 20)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPE (STM32F3X_CLOCK_AHB_BASE | 1 << 21)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPF (STM32F3X_CLOCK_AHB_BASE | 1 << 22)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_IOPG (STM32F3X_CLOCK_AHB_BASE | 1 << 23)
|
||||
#endif
|
||||
#define STM32F3X_CLOCK_SUBSYS_TSC (STM32F3X_CLOCK_AHB_BASE | 1 << 24)
|
||||
#define STM32F3X_CLOCK_SUBSYS_ADC12 (STM32F3X_CLOCK_AHB_BASE | 1 << 28)
|
||||
#ifndef CONFIG_SOC_STM32F334X8
|
||||
#define STM32F3X_CLOCK_SUBSYS_ADC34 (STM32F3X_CLOCK_AHB_BASE | 1 << 29)
|
||||
#endif
|
||||
|
||||
#endif /* _STM32F3_CLOCK_CONTROL_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue