1 /*
2  * Copyright (c) 2018 Workaround GmbH
3  * Copyright (c) 2018 Allterco Robotics
4  * Copyright (c) 2018 Linaro Limited
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * Source file for the STM32 RTC driver
9  *
10  */
11 
12 #define DT_DRV_COMPAT st_stm32_rtc
13 
14 #include <time.h>
15 
16 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
17 #include <zephyr/drivers/clock_control.h>
18 #include <zephyr/sys/util.h>
19 #include <zephyr/kernel.h>
20 #include <soc.h>
21 #include <stm32_ll_exti.h>
22 #include <stm32_ll_pwr.h>
23 #include <stm32_ll_rcc.h>
24 #include <stm32_ll_rtc.h>
25 #include <zephyr/drivers/counter.h>
26 #include <zephyr/sys/timeutil.h>
27 
28 #include <zephyr/logging/log.h>
29 #include <zephyr/irq.h>
30 
31 #include "stm32_hsem.h"
32 
33 LOG_MODULE_REGISTER(counter_rtc_stm32, CONFIG_COUNTER_LOG_LEVEL);
34 
35 /* Seconds from 1970-01-01T00:00:00 to 2000-01-01T00:00:00 */
36 #define T_TIME_OFFSET 946684800
37 
38 #if defined(CONFIG_SOC_SERIES_STM32L4X)
39 #define RTC_EXTI_LINE	LL_EXTI_LINE_18
40 #elif defined(CONFIG_SOC_SERIES_STM32C0X) \
41 	|| defined(CONFIG_SOC_SERIES_STM32G0X)
42 #define RTC_EXTI_LINE	LL_EXTI_LINE_19
43 #elif defined(CONFIG_SOC_SERIES_STM32F4X) \
44 	|| defined(CONFIG_SOC_SERIES_STM32F0X) \
45 	|| defined(CONFIG_SOC_SERIES_STM32F1X) \
46 	|| defined(CONFIG_SOC_SERIES_STM32F2X) \
47 	|| defined(CONFIG_SOC_SERIES_STM32F3X) \
48 	|| defined(CONFIG_SOC_SERIES_STM32F7X) \
49 	|| defined(CONFIG_SOC_SERIES_STM32WBX) \
50 	|| defined(CONFIG_SOC_SERIES_STM32G4X) \
51 	|| defined(CONFIG_SOC_SERIES_STM32L0X) \
52 	|| defined(CONFIG_SOC_SERIES_STM32L1X) \
53 	|| defined(CONFIG_SOC_SERIES_STM32L5X) \
54 	|| defined(CONFIG_SOC_SERIES_STM32H7X) \
55 	|| defined(CONFIG_SOC_SERIES_STM32H5X) \
56 	|| defined(CONFIG_SOC_SERIES_STM32WLX)
57 #define RTC_EXTI_LINE	LL_EXTI_LINE_17
58 #endif
59 
60 #if defined(CONFIG_SOC_SERIES_STM32F1X)
61 #define COUNTER_NO_DATE
62 #endif
63 
64 struct rtc_stm32_config {
65 	struct counter_config_info counter_info;
66 	LL_RTC_InitTypeDef ll_rtc_config;
67 	const struct stm32_pclken *pclken;
68 };
69 
70 struct rtc_stm32_data {
71 	counter_alarm_callback_t callback;
72 	uint32_t ticks;
73 	void *user_data;
74 };
75 
ll_func_init_alarm(RTC_TypeDef * rtc,uint32_t format,LL_RTC_AlarmTypeDef * alarmStruct)76 static inline ErrorStatus ll_func_init_alarm(RTC_TypeDef *rtc, uint32_t format,
77 					     LL_RTC_AlarmTypeDef *alarmStruct)
78 {
79 #if defined(CONFIG_SOC_SERIES_STM32F1X)
80 	return LL_RTC_ALARM_Init(rtc, format, alarmStruct);
81 #else
82 	return LL_RTC_ALMA_Init(rtc, format, alarmStruct);
83 #endif
84 }
85 
ll_func_clear_alarm_flag(RTC_TypeDef * rtc)86 static inline void ll_func_clear_alarm_flag(RTC_TypeDef *rtc)
87 {
88 #if defined(CONFIG_SOC_SERIES_STM32F1X)
89 	LL_RTC_ClearFlag_ALR(rtc);
90 #else
91 	LL_RTC_ClearFlag_ALRA(rtc);
92 #endif
93 }
94 
ll_func_is_active_alarm(RTC_TypeDef * rtc)95 static inline uint32_t ll_func_is_active_alarm(RTC_TypeDef *rtc)
96 {
97 #if defined(CONFIG_SOC_SERIES_STM32F1X)
98 	return LL_RTC_IsActiveFlag_ALR(rtc);
99 #else
100 	return LL_RTC_IsActiveFlag_ALRA(rtc);
101 #endif
102 }
103 
ll_func_enable_interrupt_alarm(RTC_TypeDef * rtc)104 static inline void ll_func_enable_interrupt_alarm(RTC_TypeDef *rtc)
105 {
106 #if defined(CONFIG_SOC_SERIES_STM32F1X)
107 	LL_RTC_EnableIT_ALR(rtc);
108 #else
109 	LL_RTC_EnableIT_ALRA(rtc);
110 #endif
111 }
112 
ll_func_disable_interrupt_alarm(RTC_TypeDef * rtc)113 static inline void ll_func_disable_interrupt_alarm(RTC_TypeDef *rtc)
114 {
115 #if defined(CONFIG_SOC_SERIES_STM32F1X)
116 	LL_RTC_DisableIT_ALR(rtc);
117 #else
118 	LL_RTC_DisableIT_ALRA(rtc);
119 #endif
120 }
121 
ll_func_enable_alarm(RTC_TypeDef * rtc)122 static inline void ll_func_enable_alarm(RTC_TypeDef *rtc)
123 {
124 #if defined(CONFIG_SOC_SERIES_STM32F1X)
125 	ARG_UNUSED(rtc);
126 #else
127 	LL_RTC_ALMA_Enable(rtc);
128 #endif
129 }
130 
ll_func_disable_alarm(RTC_TypeDef * rtc)131 static inline void ll_func_disable_alarm(RTC_TypeDef *rtc)
132 {
133 #if defined(CONFIG_SOC_SERIES_STM32F1X)
134 	ARG_UNUSED(rtc);
135 #else
136 	LL_RTC_ALMA_Disable(rtc);
137 #endif
138 }
139 
140 static void rtc_stm32_irq_config(const struct device *dev);
141 
142 
rtc_stm32_start(const struct device * dev)143 static int rtc_stm32_start(const struct device *dev)
144 {
145 	ARG_UNUSED(dev);
146 
147 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
148 	LL_RCC_EnableRTC();
149 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
150 
151 	return 0;
152 }
153 
154 
rtc_stm32_stop(const struct device * dev)155 static int rtc_stm32_stop(const struct device *dev)
156 {
157 	ARG_UNUSED(dev);
158 
159 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
160 	LL_RCC_DisableRTC();
161 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
162 
163 	return 0;
164 }
165 
166 
rtc_stm32_read(const struct device * dev)167 static uint32_t rtc_stm32_read(const struct device *dev)
168 {
169 #if !defined(COUNTER_NO_DATE)
170 	struct tm now = { 0 };
171 	time_t ts;
172 	uint32_t rtc_date, rtc_time, ticks;
173 #else
174 	uint32_t rtc_time, ticks;
175 #endif
176 	ARG_UNUSED(dev);
177 
178 	/* Read time and date registers */
179 	rtc_time = LL_RTC_TIME_Get(RTC);
180 #if !defined(COUNTER_NO_DATE)
181 	rtc_date = LL_RTC_DATE_Get(RTC);
182 #endif
183 
184 #if !defined(COUNTER_NO_DATE)
185 	/* Convert calendar datetime to UNIX timestamp */
186 	/* RTC start time: 1st, Jan, 2000 */
187 	/* time_t start:   1st, Jan, 1970 */
188 	now.tm_year = 100 +
189 			__LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(rtc_date));
190 	/* tm_mon allowed values are 0-11 */
191 	now.tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(rtc_date)) - 1;
192 	now.tm_mday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_DAY(rtc_date));
193 
194 	now.tm_hour = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_HOUR(rtc_time));
195 	now.tm_min = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MINUTE(rtc_time));
196 	now.tm_sec = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_SECOND(rtc_time));
197 
198 	ts = timeutil_timegm(&now);
199 
200 	/* Return number of seconds since RTC init */
201 	ts -= T_TIME_OFFSET;
202 
203 	__ASSERT(sizeof(time_t) == 8, "unexpected time_t definition");
204 	ticks = counter_us_to_ticks(dev, ts * USEC_PER_SEC);
205 #else
206 	ticks = rtc_time;
207 #endif
208 
209 	return ticks;
210 }
211 
rtc_stm32_get_value(const struct device * dev,uint32_t * ticks)212 static int rtc_stm32_get_value(const struct device *dev, uint32_t *ticks)
213 {
214 	*ticks = rtc_stm32_read(dev);
215 	return 0;
216 }
217 
rtc_stm32_set_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)218 static int rtc_stm32_set_alarm(const struct device *dev, uint8_t chan_id,
219 				const struct counter_alarm_cfg *alarm_cfg)
220 {
221 #if !defined(COUNTER_NO_DATE)
222 	struct tm alarm_tm;
223 	time_t alarm_val;
224 #else
225 	uint32_t remain;
226 #endif
227 	LL_RTC_AlarmTypeDef rtc_alarm;
228 	struct rtc_stm32_data *data = dev->data;
229 
230 	uint32_t now = rtc_stm32_read(dev);
231 	uint32_t ticks = alarm_cfg->ticks;
232 
233 	if (data->callback != NULL) {
234 		LOG_DBG("Alarm busy\n");
235 		return -EBUSY;
236 	}
237 
238 
239 	data->callback = alarm_cfg->callback;
240 	data->user_data = alarm_cfg->user_data;
241 
242 #if !defined(COUNTER_NO_DATE)
243 	if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
244 		/* Add +1 in order to compensate the partially started tick.
245 		 * Alarm will expire between requested ticks and ticks+1.
246 		 * In case only 1 tick is requested, it will avoid
247 		 * that tick+1 event occurs before alarm setting is finished.
248 		 */
249 		ticks += now + 1;
250 		alarm_val = (time_t)(counter_ticks_to_us(dev, ticks) / USEC_PER_SEC)
251 			+ T_TIME_OFFSET;
252 	} else {
253 		alarm_val = (time_t)(counter_ticks_to_us(dev, ticks) / USEC_PER_SEC);
254 	}
255 #else
256 	if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
257 		remain = ticks + now + 1;
258 	} else {
259 		remain = ticks;
260 	}
261 
262 	/* In F1X, an interrupt occurs when the counter expires,
263 	 * not when the counter matches, so set -1
264 	 */
265 	remain--;
266 #endif
267 
268 #if !defined(COUNTER_NO_DATE)
269 	LOG_DBG("Set Alarm: %d\n", ticks);
270 
271 	gmtime_r(&alarm_val, &alarm_tm);
272 
273 	/* Apply ALARM_A */
274 	rtc_alarm.AlarmTime.TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24;
275 	rtc_alarm.AlarmTime.Hours = alarm_tm.tm_hour;
276 	rtc_alarm.AlarmTime.Minutes = alarm_tm.tm_min;
277 	rtc_alarm.AlarmTime.Seconds = alarm_tm.tm_sec;
278 
279 	rtc_alarm.AlarmMask = LL_RTC_ALMA_MASK_NONE;
280 	rtc_alarm.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
281 	rtc_alarm.AlarmDateWeekDay = alarm_tm.tm_mday;
282 #else
283 	rtc_alarm.AlarmTime.Hours = remain / 3600;
284 	remain -= rtc_alarm.AlarmTime.Hours * 3600;
285 	rtc_alarm.AlarmTime.Minutes = remain / 60;
286 	remain -= rtc_alarm.AlarmTime.Minutes * 60;
287 	rtc_alarm.AlarmTime.Seconds = remain;
288 #endif
289 
290 	LL_RTC_DisableWriteProtection(RTC);
291 	ll_func_disable_alarm(RTC);
292 	LL_RTC_EnableWriteProtection(RTC);
293 
294 	if (ll_func_init_alarm(RTC, LL_RTC_FORMAT_BIN, &rtc_alarm) != SUCCESS) {
295 		return -EIO;
296 	}
297 
298 	LL_RTC_DisableWriteProtection(RTC);
299 	ll_func_enable_alarm(RTC);
300 	ll_func_clear_alarm_flag(RTC);
301 	ll_func_enable_interrupt_alarm(RTC);
302 	LL_RTC_EnableWriteProtection(RTC);
303 
304 	return 0;
305 }
306 
307 
rtc_stm32_cancel_alarm(const struct device * dev,uint8_t chan_id)308 static int rtc_stm32_cancel_alarm(const struct device *dev, uint8_t chan_id)
309 {
310 	struct rtc_stm32_data *data = dev->data;
311 
312 	LL_RTC_DisableWriteProtection(RTC);
313 	ll_func_clear_alarm_flag(RTC);
314 	ll_func_disable_interrupt_alarm(RTC);
315 	ll_func_disable_alarm(RTC);
316 	LL_RTC_EnableWriteProtection(RTC);
317 
318 	data->callback = NULL;
319 
320 	return 0;
321 }
322 
323 
rtc_stm32_get_pending_int(const struct device * dev)324 static uint32_t rtc_stm32_get_pending_int(const struct device *dev)
325 {
326 	return ll_func_is_active_alarm(RTC) != 0;
327 }
328 
329 
rtc_stm32_get_top_value(const struct device * dev)330 static uint32_t rtc_stm32_get_top_value(const struct device *dev)
331 {
332 	const struct counter_config_info *info = dev->config;
333 
334 	return info->max_top_value;
335 }
336 
337 
rtc_stm32_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)338 static int rtc_stm32_set_top_value(const struct device *dev,
339 				   const struct counter_top_cfg *cfg)
340 {
341 	const struct counter_config_info *info = dev->config;
342 
343 	if ((cfg->ticks != info->max_top_value) ||
344 		!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
345 		return -ENOTSUP;
346 	} else {
347 		return 0;
348 	}
349 
350 
351 }
352 
rtc_stm32_isr(const struct device * dev)353 void rtc_stm32_isr(const struct device *dev)
354 {
355 	struct rtc_stm32_data *data = dev->data;
356 	counter_alarm_callback_t alarm_callback = data->callback;
357 
358 	uint32_t now = rtc_stm32_read(dev);
359 
360 	if (ll_func_is_active_alarm(RTC) != 0) {
361 
362 		LL_RTC_DisableWriteProtection(RTC);
363 		ll_func_clear_alarm_flag(RTC);
364 		ll_func_disable_interrupt_alarm(RTC);
365 		ll_func_disable_alarm(RTC);
366 		LL_RTC_EnableWriteProtection(RTC);
367 
368 		if (alarm_callback != NULL) {
369 			data->callback = NULL;
370 			alarm_callback(dev, 0, now, data->user_data);
371 		}
372 	}
373 
374 #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
375 	LL_C2_EXTI_ClearFlag_0_31(RTC_EXTI_LINE);
376 #elif defined(CONFIG_SOC_SERIES_STM32C0X) \
377 	|| defined(CONFIG_SOC_SERIES_STM32G0X) \
378 	|| defined(CONFIG_SOC_SERIES_STM32L5X) \
379 	|| defined(CONFIG_SOC_SERIES_STM32H5X)
380 	LL_EXTI_ClearRisingFlag_0_31(RTC_EXTI_LINE);
381 #elif defined(CONFIG_SOC_SERIES_STM32U5X)
382 	/* in STM32U5 family RTC is not connected to EXTI */
383 #else
384 	LL_EXTI_ClearFlag_0_31(RTC_EXTI_LINE);
385 #endif
386 }
387 
388 
rtc_stm32_init(const struct device * dev)389 static int rtc_stm32_init(const struct device *dev)
390 {
391 	const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
392 	const struct rtc_stm32_config *cfg = dev->config;
393 	struct rtc_stm32_data *data = dev->data;
394 
395 	data->callback = NULL;
396 
397 	if (!device_is_ready(clk)) {
398 		LOG_ERR("clock control device not ready");
399 		return -ENODEV;
400 	}
401 
402 	/* Enable RTC bus clock */
403 	if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) {
404 		LOG_ERR("clock op failed\n");
405 		return -EIO;
406 	}
407 
408 	/* Enable Backup access */
409 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
410 #if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || \
411 	defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP)
412 	LL_PWR_EnableBkUpAccess();
413 #endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */
414 
415 	/* Enable RTC clock source */
416 	if (clock_control_configure(clk,
417 				    (clock_control_subsys_t) &cfg->pclken[1],
418 				    NULL) != 0) {
419 		LOG_ERR("clock configure failed\n");
420 		return -EIO;
421 	}
422 
423 	LL_RCC_EnableRTC();
424 
425 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
426 
427 #if !defined(CONFIG_COUNTER_RTC_STM32_SAVE_VALUE_BETWEEN_RESETS)
428 	if (LL_RTC_DeInit(RTC) != SUCCESS) {
429 		return -EIO;
430 	}
431 #endif
432 
433 	if (LL_RTC_Init(RTC, ((LL_RTC_InitTypeDef *)
434 			      &cfg->ll_rtc_config)) != SUCCESS) {
435 		return -EIO;
436 	}
437 
438 #ifdef RTC_CR_BYPSHAD
439 	LL_RTC_DisableWriteProtection(RTC);
440 	LL_RTC_EnableShadowRegBypass(RTC);
441 	LL_RTC_EnableWriteProtection(RTC);
442 #endif /* RTC_CR_BYPSHAD */
443 
444 #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
445 	LL_C2_EXTI_EnableIT_0_31(RTC_EXTI_LINE);
446 	LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE);
447 #elif defined(CONFIG_SOC_SERIES_STM32U5X)
448 	/* in STM32U5 family RTC is not connected to EXTI */
449 #else
450 	LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE);
451 	LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE);
452 #endif
453 
454 	rtc_stm32_irq_config(dev);
455 
456 	return 0;
457 }
458 
459 static struct rtc_stm32_data rtc_data;
460 
461 #if DT_INST_NUM_CLOCKS(0) == 1
462 #warning STM32 RTC needs a kernel source clock. Please define it in dts file
463 static const struct stm32_pclken rtc_clk[] = {
464 	STM32_CLOCK_INFO(0, DT_DRV_INST(0)),
465 	/* Use Kconfig to configure source clocks fields (Deprecated) */
466 	/* Fortunately, values are consistent across enabled series */
467 #ifdef CONFIG_COUNTER_RTC_STM32_CLOCK_LSE
468 	{.bus = STM32_SRC_LSE, .enr = RTC_SEL(1)}
469 #else
470 	{.bus = STM32_SRC_LSI, .enr = RTC_SEL(2)}
471 #endif
472 };
473 #else
474 static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0);
475 #endif
476 
477 static const struct rtc_stm32_config rtc_config = {
478 	.counter_info = {
479 		.max_top_value = UINT32_MAX,
480 		.freq = 1,
481 		.flags = COUNTER_CONFIG_INFO_COUNT_UP,
482 		.channels = 1,
483 	},
484 	.ll_rtc_config = {
485 #if !defined(CONFIG_SOC_SERIES_STM32F1X)
486 		.HourFormat = LL_RTC_HOURFORMAT_24HOUR,
487 #if DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSI
488 		/* prescaler values for LSI @ 32 KHz */
489 		.AsynchPrescaler = 0x7F,
490 		.SynchPrescaler = 0x00F9,
491 #else /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */
492 		/* prescaler values for LSE @ 32768 Hz */
493 		.AsynchPrescaler = 0x7F,
494 		.SynchPrescaler = 0x00FF,
495 #endif
496 #else /* CONFIG_SOC_SERIES_STM32F1X */
497 #if DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSI
498 		/* prescaler values for LSI @ 40 KHz */
499 		.AsynchPrescaler = 0x9C3F,
500 #else /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */
501 		/* prescaler values for LSE @ 32768 Hz */
502 		.AsynchPrescaler = 0x7FFF,
503 #endif /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */
504 		.OutPutSource = LL_RTC_CALIB_OUTPUT_NONE,
505 #endif /* CONFIG_SOC_SERIES_STM32F1X */
506 	},
507 	.pclken = rtc_clk,
508 };
509 
510 
511 static const struct counter_driver_api rtc_stm32_driver_api = {
512 		.start = rtc_stm32_start,
513 		.stop = rtc_stm32_stop,
514 		.get_value = rtc_stm32_get_value,
515 		.set_alarm = rtc_stm32_set_alarm,
516 		.cancel_alarm = rtc_stm32_cancel_alarm,
517 		.set_top_value = rtc_stm32_set_top_value,
518 		.get_pending_int = rtc_stm32_get_pending_int,
519 		.get_top_value = rtc_stm32_get_top_value,
520 };
521 
522 DEVICE_DT_INST_DEFINE(0, &rtc_stm32_init, NULL,
523 		    &rtc_data, &rtc_config, PRE_KERNEL_1,
524 		    CONFIG_COUNTER_INIT_PRIORITY, &rtc_stm32_driver_api);
525 
rtc_stm32_irq_config(const struct device * dev)526 static void rtc_stm32_irq_config(const struct device *dev)
527 {
528 	IRQ_CONNECT(DT_INST_IRQN(0),
529 		    DT_INST_IRQ(0, priority),
530 		    rtc_stm32_isr, DEVICE_DT_INST_GET(0), 0);
531 	irq_enable(DT_INST_IRQN(0));
532 }
533