Skip to content

drivers: rtc: STM32 rtc scalers #89313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 51 additions & 6 deletions drivers/counter/counter_ll_stm32_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ struct rtc_stm32_config {
struct counter_config_info counter_info;
LL_RTC_InitTypeDef ll_rtc_config;
const struct stm32_pclken *pclken;
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
uint32_t hse_prescaler;
#endif
};

struct rtc_stm32_data {
Expand Down Expand Up @@ -593,6 +596,11 @@ static int rtc_stm32_init(const struct device *dev)
}
#endif

#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
/* Must be configured before selecting the RTC clock source */
LL_RCC_SetRTC_HSEPrescaler(cfg->hse_prescaler);
#endif

if (LL_RTC_Init(RTC, ((LL_RTC_InitTypeDef *)
&cfg->ll_rtc_config)) != SUCCESS) {
return -EIO;
Expand Down Expand Up @@ -623,28 +631,65 @@ static struct rtc_stm32_data rtc_data;

static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0);

#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
#if STM32_HSE_FREQ % MHZ(1) != 0
#error RTC clock source HSE frequency should be whole MHz
#elif STM32_HSE_FREQ < MHZ(16) && defined(LL_RCC_RTC_HSE_DIV_16)
#define RTC_HSE_PRESCALER LL_RCC_RTC_HSE_DIV_16
#define RTC_HSE_FREQUENCY (STM32_HSE_FREQ / 16)
#elif STM32_HSE_FREQ < MHZ(32) && defined(LL_RCC_RTC_HSE_DIV_32)
#define RTC_HSE_PRESCALER LL_RCC_RTC_HSE_DIV_32
#define RTC_HSE_FREQUENCY (STM32_HSE_FREQ / 32)
#elif STM32_HSE_FREQ < MHZ(64) && defined(LL_RCC_RTC_HSE_DIV_64)
#define RTC_HSE_PRESCALER LL_RCC_RTC_HSE_DIV_64
#define RTC_HSE_FREQUENCY (STM32_HSE_FREQ / 64)
#else
#error RTC does not support HSE frequency
#endif
#define RTC_HSE_ASYNC_PRESCALER 125
#define RTC_HSE_SYNC_PRESCALER (RTC_HSE_FREQUENCY / RTC_HSE_ASYNC_PRESCALER)
#endif /* DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE */

static const struct rtc_stm32_config rtc_config = {
.counter_info = {
.max_top_value = UINT32_MAX,
#ifndef CONFIG_COUNTER_RTC_STM32_SUBSECONDS
/* freq = 1Hz for not subsec based driver */
.freq = RTCCLK_FREQ / ((RTC_ASYNCPRE + 1) * (RTC_SYNCPRE + 1)),
#else /* !CONFIG_COUNTER_RTC_STM32_SUBSECONDS */
#else /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */
.freq = RTCCLK_FREQ / (RTC_ASYNCPRE + 1),
#endif /* CONFIG_COUNTER_RTC_STM32_SUBSECONDS */
#endif
.flags = COUNTER_CONFIG_INFO_COUNT_UP,
.channels = 1,
},
.ll_rtc_config = {
.AsynchPrescaler = RTC_ASYNCPRE,
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI || \
DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSE
.AsynchPrescaler = DT_INST_PROP_OR(0, async_prescaler, RTC_ASYNCPRE),
#if !defined(CONFIG_SOC_SERIES_STM32F1X)
.HourFormat = LL_RTC_HOURFORMAT_24HOUR,
.SynchPrescaler = RTC_SYNCPRE,
#else /* CONFIG_SOC_SERIES_STM32F1X */
.SynchPrescaler = DT_INST_PROP_OR(0, sync_prescaler, RTC_SYNCPRE),
#else /* CONFIG_SOC_SERIES_STM32F1X */
.OutPutSource = LL_RTC_CALIB_OUTPUT_NONE,
#endif /* CONFIG_SOC_SERIES_STM32F1X */
#endif /* !CONFIG_SOC_SERIES_STM32F1X */
#elif DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
.AsynchPrescaler =
DT_INST_PROP_OR(0, async_prescaler, _HSE_ASYNC_PRESCALER - 1),
#if !defined(CONFIG_SOC_SERIES_STM32F1X)
.HourFormat = LL_RTC_HOURFORMAT_24HOUR,
.SynchPrescaler =
DT_INST_PROP_OR(0, hse_prescaler, RTC_HSE_SYNC_PRESCALER - 1),
#else /* CONFIG_SOC_SERIES_STM32F1X */
.OutPutSource = LL_RTC_CALIB_OUTPUT_NONE,
#endif /* !CONFIG_SOC_SERIES_STM32F1X */
#else
#error Invalid RTC SRC
#endif
},
.pclken = rtc_clk,
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
.hse_prescaler = DT_INST_PROP_OR(0, hse_prescaler, RTC_HSE_PRESCALER),
#endif
};

#ifdef CONFIG_PM_DEVICE
Expand Down
14 changes: 7 additions & 7 deletions drivers/rtc/rtc_ll_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,17 +1114,17 @@ BUILD_ASSERT(DT_INST_CLOCKS_HAS_IDX(0, 1), "RTC source clock not defined in the
static const struct rtc_stm32_config rtc_config = {
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI
/* prescaler values for LSI @ 32 KHz */
.async_prescaler = 0x7F,
.sync_prescaler = 0x00F9,
.async_prescaler = DT_INST_PROP_OR(0, async_prescaler, 0x7F),
.sync_prescaler = DT_INST_PROP_OR(0, sync_prescaler, 0x00F9),
#elif DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSE
/* prescaler values for LSE @ 32768 Hz */
.async_prescaler = 0x7F,
.sync_prescaler = 0x00FF,
.async_prescaler = DT_INST_PROP_OR(0, async_prescaler, 0x7F),
.sync_prescaler = DT_INST_PROP_OR(0, sync_prescaler, 0x00FF),
#elif DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
/* prescaler values for HSE */
.async_prescaler = RTC_HSE_ASYNC_PRESCALER - 1,
.sync_prescaler = RTC_HSE_SYNC_PRESCALER - 1,
.hse_prescaler = RTC_HSE_PRESCALER,
.async_prescaler = DT_INST_PROP_OR(0, async_prescaler, RTC_HSE_ASYNC_PRESCALER - 1),
.sync_prescaler = DT_INST_PROP_OR(0, sync_prescaler, RTC_HSE_SYNC_PRESCALER - 1),
.hse_prescaler = DT_INST_PROP_OR(0, hse_prescaler, RTC_HSE_PRESCALER),
#else
#error Invalid RTC SRC
#endif
Expand Down
21 changes: 21 additions & 0 deletions dts/bindings/rtc/st,stm32-rtc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ properties:
reg:
required: true

sync-prescaler:
type: int
description: |
RTC synchronous prescaler value. Optional, if not set defaulted in code to:
- Selected to give 1 Hz tick rate, bsed on source clock frequency and asynchronous
prescaler value

async-prescaler:
type: int
description: |
RTC asynchronous prescaler value. Optional, if not set defaulted in code to:
- 0x7F if RTC source clock is LSE/LSI
- 1 if using counter with CONFIG_COUNTER_RTC_STM32_SUBSECONDS option
- 0x7C if RTC source clock is HSE

hse-prescaler:
type: int
description: |
RTC HSE prescaler value. Applies only when RTC source clock is HSE.
Optional, defaulting to the value calculated based on HSE clock frequency.

calib-out-freq:
type: int
description: |
Expand Down