drivers/clock_control: stm32h7: Add support for alt clocks
Add support for alternate clocks configuration. Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
This commit is contained in:
parent
78f40773b8
commit
833eda84d3
2 changed files with 276 additions and 13 deletions
|
@ -17,6 +17,7 @@
|
|||
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
|
||||
#include "stm32_hsem.h"
|
||||
|
||||
|
||||
/* Macros to fill up prescaler values */
|
||||
#define z_hsi_divider(v) LL_RCC_HSI_DIV ## v
|
||||
#define hsi_divider(v) z_hsi_divider(v)
|
||||
|
@ -168,9 +169,9 @@ static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
|
|||
|
||||
__unused
|
||||
static uint32_t get_pllout_frequency(uint32_t pllsrc_freq,
|
||||
int pllm_div,
|
||||
int plln_mul,
|
||||
int pllout_div)
|
||||
int pllm_div,
|
||||
int plln_mul,
|
||||
int pllout_div)
|
||||
{
|
||||
__ASSERT_NO_MSG(pllm_div && pllout_div);
|
||||
|
||||
|
@ -321,6 +322,28 @@ static uint32_t get_vco_output_range(uint32_t vco_input_range)
|
|||
|
||||
#endif /* ! CONFIG_CPU_CORTEX_M4 */
|
||||
|
||||
/** @brief Verifies clock is part of actve clock configuration */
|
||||
static int enabled_clock(uint32_t src_clk)
|
||||
{
|
||||
|
||||
if ((src_clk == STM32_SRC_SYSCLK) ||
|
||||
((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_HSI_KER) && IS_ENABLED(STM32_HSI_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_CSI_KER) && IS_ENABLED(STM32_CSI_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_PLL1_P) && IS_ENABLED(STM32_PLL_P_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_PLL1_Q) && IS_ENABLED(STM32_PLL_Q_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_PLL1_R) && IS_ENABLED(STM32_PLL_R_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_PLL3_P) && IS_ENABLED(STM32_PLL3_P_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_PLL3_Q) && IS_ENABLED(STM32_PLL3_Q_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_PLL3_R) && IS_ENABLED(STM32_PLL3_R_ENABLED))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static inline int stm32_clock_control_on(const struct device *dev,
|
||||
clock_control_subsys_t sub_system)
|
||||
{
|
||||
|
@ -373,6 +396,40 @@ static inline int stm32_clock_control_off(const struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int stm32_clock_control_configure(const struct device *dev,
|
||||
clock_control_subsys_t sub_system,
|
||||
void *data)
|
||||
{
|
||||
struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
|
||||
volatile uint32_t *reg;
|
||||
uint32_t reg_val, dt_val;
|
||||
int err;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(data);
|
||||
|
||||
err = enabled_clock(pclken->bus);
|
||||
if (err < 0) {
|
||||
/* Attemp to configure a src clock not available or not valid */
|
||||
return err;
|
||||
}
|
||||
|
||||
z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
|
||||
dt_val = STM32H7_CLOCK_VAL_GET(pclken->enr) <<
|
||||
STM32H7_CLOCK_SHIFT_GET(pclken->enr);
|
||||
reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) +
|
||||
STM32H7_CLOCK_REG_GET(pclken->enr));
|
||||
reg_val = *reg;
|
||||
reg_val &= ~dt_val;
|
||||
reg_val |= dt_val;
|
||||
*reg = reg_val;
|
||||
|
||||
z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_clock_control_get_subsys_rate(const struct device *clock,
|
||||
clock_control_subsys_t sub_system,
|
||||
uint32_t *rate)
|
||||
|
@ -416,6 +473,64 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
|
|||
case STM32_CLOCK_BUS_APB4:
|
||||
*rate = apb4_clock;
|
||||
break;
|
||||
case STM32_SRC_SYSCLK:
|
||||
*rate = get_hclk_frequency();
|
||||
break;
|
||||
#if defined(STM32_HSE_ENABLED)
|
||||
case STM32_SRC_HSE:
|
||||
*rate = STM32_HSE_FREQ;
|
||||
break;
|
||||
#endif /* STM32_HSE_ENABLED */
|
||||
#if defined(STM32_LSE_ENABLED)
|
||||
case STM32_SRC_LSE:
|
||||
*rate = STM32_LSE_FREQ;
|
||||
break;
|
||||
#endif /* STM32_LSE_ENABLED */
|
||||
#if defined(STM32_LSI_ENABLED)
|
||||
case STM32_SRC_LSI:
|
||||
*rate = STM32_LSI_FREQ;
|
||||
break;
|
||||
#endif /* STM32_LSI_ENABLED */
|
||||
#if defined(STM32_PLL_ENABLED)
|
||||
case STM32_SRC_PLL1_P:
|
||||
*rate = get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL_M_DIVISOR,
|
||||
STM32_PLL_N_MULTIPLIER,
|
||||
STM32_PLL_P_DIVISOR);
|
||||
break;
|
||||
case STM32_SRC_PLL1_Q:
|
||||
*rate = get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL_M_DIVISOR,
|
||||
STM32_PLL_N_MULTIPLIER,
|
||||
STM32_PLL_Q_DIVISOR);
|
||||
break;
|
||||
case STM32_SRC_PLL1_R:
|
||||
*rate = get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL_M_DIVISOR,
|
||||
STM32_PLL_N_MULTIPLIER,
|
||||
STM32_PLL_R_DIVISOR);
|
||||
break;
|
||||
#endif /* STM32_PLL_ENABLED */
|
||||
#if defined(STM32_PLL3_ENABLED)
|
||||
case STM32_SRC_PLL3_P:
|
||||
*rate = get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL3_M_DIVISOR,
|
||||
STM32_PLL3_N_MULTIPLIER,
|
||||
STM32_PLL3_P_DIVISOR);
|
||||
break;
|
||||
case STM32_SRC_PLL3_Q:
|
||||
*rate = get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL3_M_DIVISOR,
|
||||
STM32_PLL3_N_MULTIPLIER,
|
||||
STM32_PLL3_Q_DIVISOR);
|
||||
break;
|
||||
case STM32_SRC_PLL3_R:
|
||||
*rate = get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL3_M_DIVISOR,
|
||||
STM32_PLL3_N_MULTIPLIER,
|
||||
STM32_PLL3_R_DIVISOR);
|
||||
break;
|
||||
#endif /* STM32_PLL3_ENABLED */
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -427,6 +542,7 @@ static struct clock_control_driver_api stm32_clock_control_api = {
|
|||
.on = stm32_clock_control_on,
|
||||
.off = stm32_clock_control_off,
|
||||
.get_rate = stm32_clock_control_get_subsys_rate,
|
||||
.configure = stm32_clock_control_configure,
|
||||
};
|
||||
|
||||
__unused
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue