drivers/clock_control: stm32u5: Add support for optional clocks config
This change updates stm32u5 driver to support configuration of optional clocks on peripherals. Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
This commit is contained in:
parent
c9f5113d80
commit
424f937c2b
2 changed files with 139 additions and 1 deletions
|
@ -71,6 +71,57 @@ static uint32_t get_startup_frequency(void)
|
|||
}
|
||||
}
|
||||
|
||||
__unused
|
||||
static uint32_t get_pllout_frequency(uint32_t pllsrc_freq,
|
||||
int pllm_div,
|
||||
int plln_mul,
|
||||
int pllout_div)
|
||||
{
|
||||
__ASSERT_NO_MSG(pllm_div && pllout_div);
|
||||
|
||||
return (pllsrc_freq * plln_mul) /
|
||||
(pllm_div * pllout_div);
|
||||
}
|
||||
|
||||
static uint32_t get_sysclk_frequency(void)
|
||||
{
|
||||
#if defined(STM32_SYSCLK_SRC_PLL)
|
||||
return get_pllout_frequency(get_pllsrc_frequency(),
|
||||
STM32_PLL_M_DIVISOR,
|
||||
STM32_PLL_N_MULTIPLIER,
|
||||
STM32_PLL_R_DIVISOR);
|
||||
#elif defined(STM32_SYSCLK_SRC_MSIS)
|
||||
return get_msis_frequency();
|
||||
#elif defined(STM32_SYSCLK_SRC_HSE
|
||||
return STM32_HSE_FREQ;
|
||||
#elif defined(STM32_SYSCLK_SRC_HSI)) {
|
||||
return STM32_HSI_FREQ;
|
||||
#else
|
||||
__ASSERT(0, "No SYSCLK Source configured");
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/** @brief Verifies clock is part of active 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_HSI16) && IS_ENABLED(STM32_HSI_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_MSIS) && IS_ENABLED(STM32_MSIS_ENABLED)) ||
|
||||
((src_clk == STM32_SRC_MSIK) && IS_ENABLED(STM32_MSIK_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))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static inline int stm32_clock_control_on(const struct device *dev,
|
||||
clock_control_subsys_t sub_system)
|
||||
{
|
||||
|
@ -115,6 +166,35 @@ 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) {
|
||||
/* Attempt to configure a src clock not available or not valid */
|
||||
return err;
|
||||
}
|
||||
|
||||
dt_val = STM32U5_CLOCK_VAL_GET(pclken->enr) <<
|
||||
STM32U5_CLOCK_SHIFT_GET(pclken->enr);
|
||||
reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) +
|
||||
STM32U5_CLOCK_REG_GET(pclken->enr));
|
||||
reg_val = *reg;
|
||||
reg_val |= dt_val;
|
||||
*reg = reg_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_clock_control_get_subsys_rate(const struct device *dev,
|
||||
clock_control_subsys_t sys,
|
||||
uint32_t *rate)
|
||||
|
@ -156,6 +236,60 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
|
|||
case STM32_CLOCK_BUS_APB3:
|
||||
*rate = apb3_clock;
|
||||
break;
|
||||
case STM32_SRC_SYSCLK:
|
||||
*rate = get_sysclk_frequency();
|
||||
break;
|
||||
#if defined(STM32_HSI_ENABLED)
|
||||
case STM32_SRC_HSI16:
|
||||
*rate = STM32_HSI_FREQ;
|
||||
break;
|
||||
#endif /* STM32_HSI_ENABLED */
|
||||
#if defined(STM32_MSIS_ENABLED)
|
||||
case STM32_SRC_MSIS:
|
||||
*rate = get_msis_frequency();
|
||||
break;
|
||||
#endif /* STM32_MSIS_ENABLED */
|
||||
#if defined(STM32_MSIK_ENABLED)
|
||||
case STM32_SRC_MSIK:
|
||||
*rate = __LL_RCC_CALC_MSIK_FREQ(LL_RCC_MSIRANGESEL_RUN,
|
||||
STM32_MSIK_RANGE << RCC_ICSCR1_MSIKRANGE_Pos);
|
||||
break;
|
||||
#endif /* STM32_MSIK_ENABLED */
|
||||
#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 */
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -167,6 +301,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