Skip to content

Commit 4a9f883

Browse files
mathieuchopstmkartben
authored andcommitted
drivers: rtc: stm32: add support for STM32WB0 series
Modify STM32 RTC driver to support the WB0 series. Signed-off-by: Mathieu Choplain <mathieu.choplain@st.com>
1 parent 9f9f48d commit 4a9f883

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

drivers/rtc/rtc_ll_stm32.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,36 @@ static int rtc_stm32_init(const struct device *dev)
350350
return -EIO;
351351
}
352352

353+
#if defined(CONFIG_SOC_SERIES_STM32WB0X)
354+
/**
355+
* The STM32WB0 series has no bit for clock gating of RTC's APB
356+
* interface. On the other hand, the RTCEN bit that would control
357+
* whether the RTC IP is clock gated or not exists, and has been
358+
* placed in APB0ENR. The call to clock_control_on() that just
359+
* completed should have set this bit to 1.
360+
*
361+
* However, according to RefMan, the software must wait two slow
362+
* clock cycles before the IP is actually usable, due to clock
363+
* resynchronization delays. Sadly, there is no hardware register
364+
* we can poll to wait until RTC is ready...
365+
*
366+
* In worst case scenario of 24 kHz LSI, we have to wait for:
367+
* tREADY = (2 cycles / 24'000 Hz) ≅ 84µs
368+
*
369+
* Spin until that much time has elapsed, and RTC should be up.
370+
*
371+
* N.B.: we can't use k_busy_wait because it uses the SysTick
372+
* as time base, but SysTick is initialized after the RTC...
373+
*/
374+
const uint32_t cycles_to_waste =
375+
84 * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / USEC_PER_SEC);
376+
volatile uint32_t i = cycles_to_waste;
377+
378+
while (--i > 0) {
379+
/* Do nothing - loop itself burns enough cycles */
380+
}
381+
#endif /* CONFIG_SOC_SERIES_STM32WB0X */
382+
353383
k_mutex_init(&data->lock);
354384

355385
/* Enable Backup access */
@@ -362,16 +392,22 @@ static int rtc_stm32_init(const struct device *dev)
362392
LL_RCC_SetRTC_HSEPrescaler(cfg->hse_prescaler);
363393
#endif
364394
/* Enable RTC clock source */
365-
if (clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL) != 0) {
366-
LOG_ERR("clock configure failed\n");
367-
return -EIO;
395+
if (cfg->pclken[1].enr != NO_SEL) {
396+
err = clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL);
397+
398+
if (err < 0) {
399+
LOG_ERR("clock configure failed\n");
400+
return -EIO;
401+
}
368402
}
369403

370404
/*
371405
* On STM32WBAX series, there is no bit in BCDR register to enable RTC.
372406
* Enabling RTC is done directly via the RCC APB register bit.
407+
* On STM32WB0 series, LL_RCC_EnableRTC is not provided by STM32CubeWB0,
408+
* but RTC IP clock has already been turned on - skip the call as well.
373409
*/
374-
#ifndef CONFIG_SOC_SERIES_STM32WBAX
410+
#if !defined(CONFIG_SOC_SERIES_STM32WBAX) && !defined(CONFIG_SOC_SERIES_STM32WB0X)
375411
z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
376412

377413
LL_RCC_EnableRTC();

0 commit comments

Comments
 (0)