Skip to content

Commit 6446ce8

Browse files
Jeppe Odgaardnashif
authored andcommitted
drivers: rtc: rtc_ll_stm32: add hse clock support
Add support for HSE as the RTC clock source. The initial implementation has the following limitations: - Only whole MHz HSE frequency is supported, e.g. 24.5 MHz will generate a compile error. - Frequencies equal or above 64 MHz are not supported and will generate a compile error. The implementation has been tested on nucleo_h563zi with: - 8 MHz (via hse-bypass) - 25 MHz (via external crystal) Signed-off-by: Jeppe Odgaard <[email protected]>
1 parent 59655d4 commit 6446ce8

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

drivers/rtc/rtc_ll_stm32.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ struct rtc_stm32_config {
115115
#if DT_INST_NODE_HAS_PROP(0, calib_out_freq)
116116
uint32_t cal_out_freq;
117117
#endif
118+
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
119+
uint32_t hse_prescaler;
120+
#endif
118121
};
119122

120123
#ifdef CONFIG_RTC_ALARM
@@ -354,6 +357,10 @@ static int rtc_stm32_init(const struct device *dev)
354357
LL_PWR_EnableBkUpAccess();
355358
#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */
356359

360+
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
361+
/* Must be configured before selecting the RTC clock source */
362+
LL_RCC_SetRTC_HSEPrescaler(cfg->hse_prescaler);
363+
#endif
357364
/* Enable RTC clock source */
358365
if (clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL) != 0) {
359366
LOG_ERR("clock configure failed\n");
@@ -1057,15 +1064,41 @@ static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0);
10571064

10581065
BUILD_ASSERT(DT_INST_CLOCKS_HAS_IDX(0, 1), "RTC source clock not defined in the device tree");
10591066

1067+
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
1068+
#if STM32_HSE_FREQ % MHZ(1) != 0
1069+
#error RTC clock source HSE frequency should be whole MHz
1070+
#elif STM32_HSE_FREQ < MHZ(16) && defined(LL_RCC_RTC_HSE_DIV_16)
1071+
#define RTC_HSE_PRESCALER LL_RCC_RTC_HSE_DIV_16
1072+
#define RTC_HSE_FREQUENCY (STM32_HSE_FREQ / 16)
1073+
#elif STM32_HSE_FREQ < MHZ(32) && defined(LL_RCC_RTC_HSE_DIV_32)
1074+
#define RTC_HSE_PRESCALER LL_RCC_RTC_HSE_DIV_32
1075+
#define RTC_HSE_FREQUENCY (STM32_HSE_FREQ / 32)
1076+
#elif STM32_HSE_FREQ < MHZ(64) && defined(LL_RCC_RTC_HSE_DIV_64)
1077+
#define RTC_HSE_PRESCALER LL_RCC_RTC_HSE_DIV_64
1078+
#define RTC_HSE_FREQUENCY (STM32_HSE_FREQ / 64)
1079+
#else
1080+
#error RTC does not support HSE frequency
1081+
#endif
1082+
#define RTC_HSE_ASYNC_PRESCALER 125
1083+
#define RTC_HSE_SYNC_PRESCALER (RTC_HSE_FREQUENCY / RTC_HSE_ASYNC_PRESCALER)
1084+
#endif /* DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE */
1085+
10601086
static const struct rtc_stm32_config rtc_config = {
10611087
#if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI
10621088
/* prescaler values for LSI @ 32 KHz */
10631089
.async_prescaler = 0x7F,
10641090
.sync_prescaler = 0x00F9,
1065-
#else /* DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSE */
1091+
#elif DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSE
10661092
/* prescaler values for LSE @ 32768 Hz */
10671093
.async_prescaler = 0x7F,
10681094
.sync_prescaler = 0x00FF,
1095+
#elif DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_HSE
1096+
/* prescaler values for HSE */
1097+
.async_prescaler = RTC_HSE_ASYNC_PRESCALER - 1,
1098+
.sync_prescaler = RTC_HSE_SYNC_PRESCALER - 1,
1099+
.hse_prescaler = RTC_HSE_PRESCALER,
1100+
#else
1101+
#error Invalid RTC SRC
10691102
#endif
10701103
.pclken = rtc_clk,
10711104
#if DT_INST_NODE_HAS_PROP(0, calib_out_freq)

0 commit comments

Comments
 (0)