drivers: timer: stm32 lptimer adjust the TICKS_PER_SEC to LPTIM clock

With low LPTIM freq when prescaler is set to 16 or 32,
the CONFIG_SYS_CLOCK_TICKS_PER_SEC must be reduced to
LPTIM CLOCK_/prescaler to avoid spurious timer wakeup activity.
Assert error if the CONFIG_SYS_CLOCK_TICKS_PER_SEC
is not compatible with the lptim clock freq.

Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
Francois Ramu 2023-11-17 09:56:07 +01:00 committed by Fabio Baltieri
parent a19eb7cf88
commit eeb7a88ff0

View file

@ -61,11 +61,26 @@ static const struct device *const clk_ctrl = DEVICE_DT_GET(STM32_CLOCK_CONTROL_N
* 0xFFFF / (LSE freq (32768Hz) / 128)
*/
static uint32_t lptim_clock_freq = KHZ(32);
static int32_t lptim_time_base;
static uint32_t lptim_clock_freq = CONFIG_STM32_LPTIM_CLOCK;
/* The prescaler given by the DTS and to apply to the lptim_clock_freq */
#define LPTIM_PRESCALER DT_PROP(DT_DRV_INST(0), st_prescaler)
static uint32_t lptim_clock_presc = DT_PROP(DT_DRV_INST(0), st_prescaler);
#if (CONFIG_STM32_LPTIM_CLOCK_LSI)
/* Kconfig defines the clock source as LSI : check coherency with DTS */
#if (DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) != STM32_SRC_LSI)
#warning CONFIG_STM32_LPTIM_CLOCK_LSI requires STM32_SRC_LSI defined as LPTIM domain clock
#endif /* STM32_SRC_LSI */
#elif (CONFIG_STM32_LPTIM_CLOCK_LSE)
/* Kconfig defines the clock source as LSE : check coherency with DTS */
#if (DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) != STM32_SRC_LSE)
#warning CONFIG_STM32_LPTIM_CLOCK_LSE requires STM32_SRC_LSE defined as LPTIM domain clock
#endif /* STM32_SRC_LSE */
#endif /* CONFIG_STM32_LPTIM_CLOCK_LSI */
/* Minimum nb of clock cycles to have to set autoreload register correctly */
#define LPTIM_GUARD_VALUE 2
@ -81,17 +96,6 @@ static bool autoreload_ready = true;
static struct k_spinlock lock;
/* For tick accuracy, a specific tick to freq ratio is expected */
/* This check assumes LSI@32KHz or LSE@32768Hz */
#if !defined(CONFIG_STM32_LPTIM_TICK_FREQ_RATIO_OVERRIDE)
#if (((DT_CLOCKS_CELL_BY_IDX(DT_DRV_INST(0), 1, bus) == STM32_SRC_LSI) && \
(CONFIG_SYS_CLOCK_TICKS_PER_SEC != 4000)) || \
((DT_CLOCKS_CELL_BY_IDX(DT_DRV_INST(0), 1, bus) == STM32_SRC_LSE) && \
(CONFIG_SYS_CLOCK_TICKS_PER_SEC != 4096)))
#warning Advised tick freq is 4096 for LSE / 4000 for LSI
#endif
#endif /* !CONFIG_STM32_LPTIM_TICK_FREQ_RATIO_OVERRIDE */
static inline bool arrm_state_get(void)
{
return (LL_LPTIM_IsActiveFlag_ARRM(LPTIM) && LL_LPTIM_IsEnabledIT_ARRM(LPTIM));
@ -387,8 +391,24 @@ static int sys_clock_driver_init(void)
return -EIO;
}
#if !defined(CONFIG_STM32_LPTIM_TICK_FREQ_RATIO_OVERRIDE)
/*
* Check coherency between CONFIG_SYS_CLOCK_TICKS_PER_SEC
* and the lptim_clock_freq which is the CONFIG_STM32_LPTIM_CLOCK reduced
* by the lptim_clock_presc
*/
if (lptim_clock_presc <= 8) {
__ASSERT(CONFIG_STM32_LPTIM_CLOCK / 8 >= CONFIG_SYS_CLOCK_TICKS_PER_SEC,
"It is recommended to set SYS_CLOCK_TICKS_PER_SEC to CONFIG_STM32_LPTIM_CLOCK/8");
} else {
__ASSERT(CONFIG_STM32_LPTIM_CLOCK / lptim_clock_presc >=
CONFIG_SYS_CLOCK_TICKS_PER_SEC,
"Set SYS_CLOCK_TICKS_PER_SEC to CONFIG_STM32_LPTIM_CLOCK/lptim_clock_presc");
}
#endif /* !CONFIG_STM32_LPTIM_TICK_FREQ_RATIO_OVERRIDE */
/* Actual lptim clock freq when the clock source is reduced by the prescaler */
lptim_clock_freq = lptim_clock_freq / LPTIM_PRESCALER;
lptim_clock_freq = lptim_clock_freq / lptim_clock_presc;
/* Clear the event flag and possible pending interrupt */
IRQ_CONNECT(DT_INST_IRQN(0),
@ -404,7 +424,8 @@ static int sys_clock_driver_init(void)
/* configure the LPTIM counter */
LL_LPTIM_SetClockSource(LPTIM, LL_LPTIM_CLK_SOURCE_INTERNAL);
/* the LPTIM clock freq is affected by the prescaler */
LL_LPTIM_SetPrescaler(LPTIM, (__CLZ(__RBIT(LPTIM_PRESCALER)) << LPTIM_CFGR_PRESC_Pos));
LL_LPTIM_SetPrescaler(LPTIM, (__CLZ(__RBIT(lptim_clock_presc)) << LPTIM_CFGR_PRESC_Pos));
#if defined(CONFIG_SOC_SERIES_STM32U5X) || \
defined(CONFIG_SOC_SERIES_STM32WBAX)
LL_LPTIM_OC_SetPolarity(LPTIM, LL_LPTIM_CHANNEL_CH1,