stm32h7: per comments, improved consistency with other rcc impls.
Reduced the sea of enums, and renamed config parameters to match other implementations, cribbing off of the G0 config, as it is closer to the level of complexity. Updated initialization code to utilize the new values. Added flash and LDO configuration from RCC init to be more consistent with STM32 platform initialization.
This commit is contained in:
parent
5f8cbb95e6
commit
4953d67aaa
@ -415,9 +415,8 @@ LGPL License Terms @ref lgpl_license
|
||||
|
||||
#define RCC_HSI_BASE_FREQUENCY 64000000UL
|
||||
|
||||
/** Enumerations for clocks in the clock tree to allow user to get the current configuration of the
|
||||
* clocks from the RCC module. These clock sources will each be tracked through the settings.
|
||||
*/
|
||||
/** Enumerations for core system/bus clocks for user/driver/system access to base bus clocks
|
||||
* not directly associated with a peripheral. */
|
||||
enum rcc_clock_source {
|
||||
RCC_CPUCLK,
|
||||
RCC_SYSCLK,
|
||||
@ -439,22 +438,11 @@ enum rcc_osc {
|
||||
RCC_LSI
|
||||
};
|
||||
|
||||
enum rcc_sysclk_mux {
|
||||
RCC_SYSCLK_PLL,
|
||||
RCC_SYSCLK_HSE,
|
||||
RCC_SYSCLK_HSI,
|
||||
};
|
||||
|
||||
enum rcc_pll_mux {
|
||||
RCC_PLL_HSI = RCC_PLLCKSELR_PLLSRC_HSI,
|
||||
RCC_PLL_HSE = RCC_PLLCKSELR_PLLSRC_HSE
|
||||
};
|
||||
|
||||
/** PLL Configuration structure. */
|
||||
struct rcc_pll_config {
|
||||
uint32_t hse_frequency; /**< User configured external crystal frequency. */
|
||||
enum rcc_sysclk_mux sysclk_mux; /**< SYSCLK source input selection. */
|
||||
enum rcc_pll_mux pll_mux; /**< PLL source input selection. */
|
||||
enum rcc_osc sysclock_source; /**< SYSCLK source input selection. */
|
||||
uint8_t pll_source; /**< RCC_PLLCKSELR_PLLSRC_xxx value. */
|
||||
uint32_t hse_frequency; /**< User specified HSE frequency, 0 if none. */
|
||||
struct pll_config {
|
||||
uint8_t divm; /**< Pre-divider value for each PLL. 0-64 integers. */
|
||||
uint16_t divn; /**< Multiplier, 0-512 integer. */
|
||||
@ -462,12 +450,14 @@ struct rcc_pll_config {
|
||||
uint8_t divq; /**< Post divider for PLLQ clock. */
|
||||
uint8_t divr; /**< Post divider for PLLR clock. */
|
||||
} pll1, pll2, pll3; /**< PLL1-PLL3 configurations. */
|
||||
uint32_t d1cfg_core_prescale; /**< Core prescaler for domain 1. */
|
||||
uint32_t d1cfg_hclk3_prescale; /**< HCLK3 prescaler for domain 1. */
|
||||
uint32_t d1cfg_pclk3_prescale; /**< APB3 Peripheral prescaler for domain 1. */
|
||||
uint32_t d2cfg_pclk1_prescale; /**< APB1 Peripheral prescaler for domain 2. */
|
||||
uint32_t d2cfg_pclk2_prescale; /**< APB2 Peripheral prescaler for domain 2. */
|
||||
uint32_t d3cfg_pclk4_prescale; /**< APB4 Peripheral prescaler for domain 3. */
|
||||
uint8_t core_pre; /**< Core prescaler note: domain 1. */
|
||||
uint8_t hpre; /**< HCLK3 prescaler note: domain 1. */
|
||||
uint8_t ppre1; /**< APB1 Peripheral prescaler note: domain 2. */
|
||||
uint8_t ppre2; /**< APB2 Peripheral prescaler note: domain 2. */
|
||||
uint8_t ppre3; /**< APB3 Peripheral prescaler note: domain 1. */
|
||||
uint8_t ppre4; /**< APB4 Peripheral prescaler note: domain 3. */
|
||||
uint8_t flash_waitstates; /**< Latency Value to set for flahs. */
|
||||
enum pwr_vos_scale voltage_scale; /**< LDO Voltage scale used for this frequency. */
|
||||
};
|
||||
|
||||
#define _REG_BIT(base, bit) (((base) << 5) + (bit))
|
||||
|
@ -110,10 +110,10 @@ static void rcc_set_and_enable_plls(const struct rcc_pll_config *config) {
|
||||
RCC_PLLCKSELR = RCC_PLLCKSELR_DIVM1(config->pll1.divm) |
|
||||
RCC_PLLCKSELR_DIVM2(config->pll2.divm) |
|
||||
RCC_PLLCKSELR_DIVM3(config->pll3.divm) |
|
||||
config->pll_mux;
|
||||
config->pll_source;
|
||||
|
||||
uint32_t clkin = (config->pll_mux == RCC_PLL_HSI) ? RCC_HSI_BASE_FREQUENCY
|
||||
: config->hse_frequency;
|
||||
uint32_t clkin = (config->pll_source == RCC_PLLCKSELR_PLLSRC_HSI)
|
||||
? RCC_HSI_BASE_FREQUENCY : config->hse_frequency;
|
||||
|
||||
RCC_PLLCFGR = 0;
|
||||
rcc_configure_pll(clkin, &config->pll1, 1);
|
||||
@ -145,38 +145,37 @@ static uint16_t rcc_prediv_3bit_log_div(uint16_t clk_mhz, uint32_t div_val) {
|
||||
|
||||
static void rcc_clock_setup_domain1(const struct rcc_pll_config *config) {
|
||||
RCC_D1CFGR = 0;
|
||||
RCC_D1CFGR |= config->d1cfg_core_prescale | config->d1cfg_hclk3_prescale |
|
||||
config->d1cfg_pclk3_prescale;
|
||||
RCC_D1CFGR |= RCC_D1CFGR_D1CPRE(config->core_pre) |
|
||||
RCC_D1CFGR_D1HPRE(config->hpre) | RCC_D1CFGR_D1PPRE(config->ppre3);
|
||||
|
||||
/* Update our clock values in our tree based on the config values. */
|
||||
rcc_clock_tree.cpu_mhz = rcc_prediv_log_skip32_div(rcc_clock_tree.sysclk_mhz,
|
||||
config->d1cfg_core_prescale >> RCC_D1CFGR_D1CPRE_SHIFT);
|
||||
|
||||
rcc_clock_tree.hclk_mhz = rcc_prediv_log_skip32_div(rcc_clock_tree.cpu_mhz,
|
||||
config->d1cfg_hclk3_prescale);
|
||||
|
||||
rcc_clock_tree.per.pclk3_mhz = rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz,
|
||||
config->d1cfg_pclk3_prescale >> RCC_D1CFGR_D1PPRE_SHIFT);
|
||||
rcc_clock_tree.cpu_mhz =
|
||||
rcc_prediv_log_skip32_div(rcc_clock_tree.sysclk_mhz, config->core_pre);
|
||||
rcc_clock_tree.hclk_mhz =
|
||||
rcc_prediv_log_skip32_div(rcc_clock_tree.cpu_mhz, config->hpre);
|
||||
rcc_clock_tree.per.pclk3_mhz =
|
||||
rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz, config->ppre3);
|
||||
}
|
||||
|
||||
static void rcc_clock_setup_domain2(const struct rcc_pll_config *config) {
|
||||
RCC_D2CFGR = 0;
|
||||
RCC_D2CFGR |= config->d2cfg_pclk1_prescale | config->d2cfg_pclk2_prescale;
|
||||
RCC_D2CFGR |= RCC_D2CFGR_D2PPRE1(config->ppre1) |
|
||||
RCC_D2CFGR_D2PPRE2(config->ppre2);
|
||||
|
||||
/* Update our clock values in our tree based on the config values. */
|
||||
rcc_clock_tree.per.pclk2_mhz = rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz,
|
||||
config->d2cfg_pclk2_prescale >> RCC_D2CFGR_D2PPRE2_SHIFT);
|
||||
rcc_clock_tree.per.pclk1_mhz = rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz,
|
||||
config->d2cfg_pclk1_prescale >> RCC_D2CFGR_D2PPRE1_SHIFT);
|
||||
rcc_clock_tree.per.pclk2_mhz =
|
||||
rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz, config->ppre2);
|
||||
rcc_clock_tree.per.pclk1_mhz =
|
||||
rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz, config->ppre1);
|
||||
}
|
||||
|
||||
static void rcc_clock_setup_domain3(const struct rcc_pll_config *config) {
|
||||
RCC_D3CFGR &= 0;
|
||||
RCC_D3CFGR |= config->d3cfg_pclk4_prescale;
|
||||
RCC_D3CFGR |= RCC_D3CFGR_D3PPRE(config->ppre4);
|
||||
|
||||
/* Update our clock values in our tree based on the config values. */
|
||||
rcc_clock_tree.per.pclk4_mhz = rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz,
|
||||
config->d3cfg_pclk4_prescale >> RCC_D3CFGR_D3PPRE_SHIFT);
|
||||
rcc_clock_tree.per.pclk4_mhz =
|
||||
rcc_prediv_3bit_log_div(rcc_clock_tree.hclk_mhz, config->ppre4);
|
||||
}
|
||||
|
||||
void rcc_clock_setup_pll(const struct rcc_pll_config *config) {
|
||||
@ -186,6 +185,18 @@ void rcc_clock_setup_pll(const struct rcc_pll_config *config) {
|
||||
while (((RCC_CFGR >> RCC_CFGR_SWS_SHIFT) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_HSI);
|
||||
RCC_CR = RCC_CR_HSION;
|
||||
|
||||
/* Now that we're safely running on HSI, let's setup the LDO. */
|
||||
pwr_set_mode_ldo();
|
||||
pwr_set_vos_scale(config->voltage_scale);
|
||||
|
||||
/* Set flash waitstates. Enable flash prefetch if we have at least 1WS */
|
||||
flash_set_ws(config->flash_waitstates);
|
||||
if (config->flash_waitstates > FLASH_ACR_LATENCY_0WS) {
|
||||
flash_prefetch_enable();
|
||||
} else {
|
||||
flash_prefetch_disable();
|
||||
}
|
||||
|
||||
/* User has specified an external oscillator, make sure we turn it on. */
|
||||
if (config->hse_frequency > 0) {
|
||||
RCC_CR |= RCC_CR_HSEON;
|
||||
@ -197,9 +208,9 @@ void rcc_clock_setup_pll(const struct rcc_pll_config *config) {
|
||||
rcc_set_and_enable_plls(config);
|
||||
|
||||
/* Populate our base sysclk settings for use with domain clocks. */
|
||||
if (config->sysclk_mux == RCC_SYSCLK_PLL) {
|
||||
if (config->sysclock_source == RCC_PLL) {
|
||||
rcc_clock_tree.sysclk_mhz = rcc_clock_tree.pll1.p_mhz;
|
||||
} else if (config->sysclk_mux == RCC_SYSCLK_HSE) {
|
||||
} else if (config->sysclock_source == RCC_HSE) {
|
||||
rcc_clock_tree.sysclk_mhz = config->hse_frequency / HZ_PER_MHZ;
|
||||
} else {
|
||||
rcc_clock_tree.sysclk_mhz = RCC_HSI_BASE_FREQUENCY / HZ_PER_MHZ;
|
||||
|
Loading…
x
Reference in New Issue
Block a user