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,
|
static inline int stm32_clock_control_on(const struct device *dev,
|
||||||
clock_control_subsys_t sub_system)
|
clock_control_subsys_t sub_system)
|
||||||
{
|
{
|
||||||
|
@ -115,6 +166,35 @@ static inline int stm32_clock_control_off(const struct device *dev,
|
||||||
return 0;
|
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,
|
static int stm32_clock_control_get_subsys_rate(const struct device *dev,
|
||||||
clock_control_subsys_t sys,
|
clock_control_subsys_t sys,
|
||||||
uint32_t *rate)
|
uint32_t *rate)
|
||||||
|
@ -156,6 +236,60 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
|
||||||
case STM32_CLOCK_BUS_APB3:
|
case STM32_CLOCK_BUS_APB3:
|
||||||
*rate = apb3_clock;
|
*rate = apb3_clock;
|
||||||
break;
|
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:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +301,7 @@ static struct clock_control_driver_api stm32_clock_control_api = {
|
||||||
.on = stm32_clock_control_on,
|
.on = stm32_clock_control_on,
|
||||||
.off = stm32_clock_control_off,
|
.off = stm32_clock_control_off,
|
||||||
.get_rate = stm32_clock_control_get_subsys_rate,
|
.get_rate = stm32_clock_control_get_subsys_rate,
|
||||||
|
.configure = stm32_clock_control_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
__unused
|
__unused
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
#define STM32_SRC_SYSCLK 0x011
|
#define STM32_SRC_SYSCLK 0x011
|
||||||
/** Clock muxes */
|
/** Clock muxes */
|
||||||
/* #define STM32_SRC_ICLK 0x012 */
|
/* #define STM32_SRC_ICLK 0x012 */
|
||||||
|
|
||||||
|
#define STM32_SRC_CLOCK_MIN STM32_SRC_PLL1_P
|
||||||
|
#define STM32_SRC_CLOCK_MAX STM32_SRC_SYSCLK
|
||||||
|
|
||||||
/** Bus clocks */
|
/** Bus clocks */
|
||||||
#define STM32_CLOCK_BUS_AHB1 0x088
|
#define STM32_CLOCK_BUS_AHB1 0x088
|
||||||
#define STM32_CLOCK_BUS_AHB2 0x08C
|
#define STM32_CLOCK_BUS_AHB2 0x08C
|
||||||
|
@ -46,7 +50,6 @@
|
||||||
#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1
|
#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1
|
||||||
#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB3
|
#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB3
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief STM32U5 clock configuration bit field.
|
* @brief STM32U5 clock configuration bit field.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue