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 <drivers/clock_control/stm32_clock_control.h>
17 #include <drivers/clock_control.h>
18 #include <sys/util.h>
19 #include <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 <drivers/counter.h>
26 #include <sys/timeutil.h>
27 
28 #include <logging/log.h>
29 
30 #include "stm32_hsem.h"
31 
32 LOG_MODULE_REGISTER(counter_rtc_stm32, CONFIG_COUNTER_LOG_LEVEL);
33 
34 /* Seconds from 1970-01-01T00:00:00 to 2000-01-01T00:00:00 */
35 #define T_TIME_OFFSET 946684800
36 
37 #if defined(CONFIG_SOC_SERIES_STM32L4X)
38 #define RTC_EXTI_LINE	LL_EXTI_LINE_18
39 #elif defined(CONFIG_SOC_SERIES_STM32G0X)
40 #define RTC_EXTI_LINE	LL_EXTI_LINE_19
41 #elif defined(CONFIG_SOC_SERIES_STM32F4X) \
42 	|| defined(CONFIG_SOC_SERIES_STM32F0X) \
43 	|| defined(CONFIG_SOC_SERIES_STM32F2X) \
44 	|| defined(CONFIG_SOC_SERIES_STM32F3X) \
45 	|| defined(CONFIG_SOC_SERIES_STM32F7X) \
46 	|| defined(CONFIG_SOC_SERIES_STM32WBX) \
47 	|| defined(CONFIG_SOC_SERIES_STM32G4X) \
48 	|| defined(CONFIG_SOC_SERIES_STM32L0X) \
49 	|| defined(CONFIG_SOC_SERIES_STM32L1X) \
50 	|| defined(CONFIG_SOC_SERIES_STM32H7X) \
51 	|| defined(CONFIG_SOC_SERIES_STM32WLX)
52 #define RTC_EXTI_LINE	LL_EXTI_LINE_17
53 #endif
54 
55 struct rtc_stm32_config {
56 	struct counter_config_info counter_info;
57 	struct stm32_pclken pclken;
58 	LL_RTC_InitTypeDef ll_rtc_config;
59 };
60 
61 struct rtc_stm32_data {
62 	counter_alarm_callback_t callback;
63 	uint32_t ticks;
64 	void *user_data;
65 };
66 
67 
68 #define DEV_DATA(dev) ((struct rtc_stm32_data *)(dev)->data)
69 #define DEV_CFG(dev)	\
70 ((const struct rtc_stm32_config * const)(dev)->config)
71 
72 
73 static void rtc_stm32_irq_config(const struct device *dev);
74 
75 
rtc_stm32_start(const struct device * dev)76 static int rtc_stm32_start(const struct device *dev)
77 {
78 	ARG_UNUSED(dev);
79 
80 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
81 	LL_RCC_EnableRTC();
82 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
83 
84 	return 0;
85 }
86 
87 
rtc_stm32_stop(const struct device * dev)88 static int rtc_stm32_stop(const struct device *dev)
89 {
90 	ARG_UNUSED(dev);
91 
92 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
93 	LL_RCC_DisableRTC();
94 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
95 
96 	return 0;
97 }
98 
99 
rtc_stm32_read(const struct device * dev)100 static uint32_t rtc_stm32_read(const struct device *dev)
101 {
102 	struct tm now = { 0 };
103 	time_t ts;
104 	uint32_t rtc_date, rtc_time, ticks;
105 
106 	ARG_UNUSED(dev);
107 
108 	/* Read time and date registers */
109 	rtc_time = LL_RTC_TIME_Get(RTC);
110 	rtc_date = LL_RTC_DATE_Get(RTC);
111 
112 	/* Convert calendar datetime to UNIX timestamp */
113 	/* RTC start time: 1st, Jan, 2000 */
114 	/* time_t start:   1st, Jan, 1970 */
115 	now.tm_year = 100 +
116 			__LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(rtc_date));
117 	/* tm_mon allowed values are 0-11 */
118 	now.tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(rtc_date)) - 1;
119 	now.tm_mday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_DAY(rtc_date));
120 
121 	now.tm_hour = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_HOUR(rtc_time));
122 	now.tm_min = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MINUTE(rtc_time));
123 	now.tm_sec = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_SECOND(rtc_time));
124 
125 	ts = timeutil_timegm(&now);
126 
127 	/* Return number of seconds since RTC init */
128 	ts -= T_TIME_OFFSET;
129 
130 	__ASSERT(sizeof(time_t) == 8, "unexpected time_t definition");
131 	ticks = counter_us_to_ticks(dev, ts * USEC_PER_SEC);
132 
133 	return ticks;
134 }
135 
rtc_stm32_get_value(const struct device * dev,uint32_t * ticks)136 static int rtc_stm32_get_value(const struct device *dev, uint32_t *ticks)
137 {
138 	*ticks = rtc_stm32_read(dev);
139 	return 0;
140 }
141 
rtc_stm32_set_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)142 static int rtc_stm32_set_alarm(const struct device *dev, uint8_t chan_id,
143 				const struct counter_alarm_cfg *alarm_cfg)
144 {
145 	struct tm alarm_tm;
146 	time_t alarm_val;
147 	LL_RTC_AlarmTypeDef rtc_alarm;
148 	struct rtc_stm32_data *data = DEV_DATA(dev);
149 
150 	uint32_t now = rtc_stm32_read(dev);
151 	uint32_t ticks = alarm_cfg->ticks;
152 
153 	if (data->callback != NULL) {
154 		LOG_DBG("Alarm busy\n");
155 		return -EBUSY;
156 	}
157 
158 
159 	data->callback = alarm_cfg->callback;
160 	data->user_data = alarm_cfg->user_data;
161 
162 	if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
163 		/* Add +1 in order to compensate the partially started tick.
164 		 * Alarm will expire between requested ticks and ticks+1.
165 		 * In case only 1 tick is requested, it will avoid
166 		 * that tick+1 event occurs before alarm setting is finished.
167 		 */
168 		ticks += now + 1;
169 		alarm_val = (time_t)(counter_ticks_to_us(dev, ticks) / USEC_PER_SEC)
170 			+ T_TIME_OFFSET;
171 	} else {
172 		alarm_val = (time_t)(counter_ticks_to_us(dev, ticks) / USEC_PER_SEC);
173 	}
174 
175 	LOG_DBG("Set Alarm: %d\n", ticks);
176 
177 	gmtime_r(&alarm_val, &alarm_tm);
178 
179 	/* Apply ALARM_A */
180 	rtc_alarm.AlarmTime.TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24;
181 	rtc_alarm.AlarmTime.Hours = alarm_tm.tm_hour;
182 	rtc_alarm.AlarmTime.Minutes = alarm_tm.tm_min;
183 	rtc_alarm.AlarmTime.Seconds = alarm_tm.tm_sec;
184 
185 	rtc_alarm.AlarmMask = LL_RTC_ALMA_MASK_NONE;
186 	rtc_alarm.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
187 	rtc_alarm.AlarmDateWeekDay = alarm_tm.tm_mday;
188 
189 	LL_RTC_DisableWriteProtection(RTC);
190 	LL_RTC_ALMA_Disable(RTC);
191 	LL_RTC_EnableWriteProtection(RTC);
192 
193 	if (LL_RTC_ALMA_Init(RTC, LL_RTC_FORMAT_BIN, &rtc_alarm) != SUCCESS) {
194 		return -EIO;
195 	}
196 
197 	LL_RTC_DisableWriteProtection(RTC);
198 	LL_RTC_ALMA_Enable(RTC);
199 	LL_RTC_ClearFlag_ALRA(RTC);
200 	LL_RTC_EnableIT_ALRA(RTC);
201 	LL_RTC_EnableWriteProtection(RTC);
202 
203 	return 0;
204 }
205 
206 
rtc_stm32_cancel_alarm(const struct device * dev,uint8_t chan_id)207 static int rtc_stm32_cancel_alarm(const struct device *dev, uint8_t chan_id)
208 {
209 	LL_RTC_DisableWriteProtection(RTC);
210 	LL_RTC_ClearFlag_ALRA(RTC);
211 	LL_RTC_DisableIT_ALRA(RTC);
212 	LL_RTC_ALMA_Disable(RTC);
213 	LL_RTC_EnableWriteProtection(RTC);
214 
215 	DEV_DATA(dev)->callback = NULL;
216 
217 	return 0;
218 }
219 
220 
rtc_stm32_get_pending_int(const struct device * dev)221 static uint32_t rtc_stm32_get_pending_int(const struct device *dev)
222 {
223 	return LL_RTC_IsActiveFlag_ALRA(RTC) != 0;
224 }
225 
226 
rtc_stm32_get_top_value(const struct device * dev)227 static uint32_t rtc_stm32_get_top_value(const struct device *dev)
228 {
229 	const struct counter_config_info *info = dev->config;
230 
231 	return info->max_top_value;
232 }
233 
234 
rtc_stm32_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)235 static int rtc_stm32_set_top_value(const struct device *dev,
236 				   const struct counter_top_cfg *cfg)
237 {
238 	const struct counter_config_info *info = dev->config;
239 
240 	if ((cfg->ticks != info->max_top_value) ||
241 		!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
242 		return -ENOTSUP;
243 	} else {
244 		return 0;
245 	}
246 
247 
248 }
249 
rtc_stm32_isr(const struct device * dev)250 void rtc_stm32_isr(const struct device *dev)
251 {
252 	struct rtc_stm32_data *data = DEV_DATA(dev);
253 	counter_alarm_callback_t alarm_callback = data->callback;
254 
255 	uint32_t now = rtc_stm32_read(dev);
256 
257 	if (LL_RTC_IsActiveFlag_ALRA(RTC) != 0) {
258 
259 		LL_RTC_DisableWriteProtection(RTC);
260 		LL_RTC_ClearFlag_ALRA(RTC);
261 		LL_RTC_DisableIT_ALRA(RTC);
262 		LL_RTC_ALMA_Disable(RTC);
263 		LL_RTC_EnableWriteProtection(RTC);
264 
265 		if (alarm_callback != NULL) {
266 			data->callback = NULL;
267 			alarm_callback(dev, 0, now, data->user_data);
268 		}
269 	}
270 
271 #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
272 	LL_C2_EXTI_ClearFlag_0_31(RTC_EXTI_LINE);
273 #elif defined(CONFIG_SOC_SERIES_STM32G0X)
274 	LL_EXTI_ClearRisingFlag_0_31(RTC_EXTI_LINE);
275 #else
276 	LL_EXTI_ClearFlag_0_31(RTC_EXTI_LINE);
277 #endif
278 }
279 
280 
rtc_stm32_init(const struct device * dev)281 static int rtc_stm32_init(const struct device *dev)
282 {
283 	const struct device *clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
284 	const struct rtc_stm32_config *cfg = DEV_CFG(dev);
285 
286 	DEV_DATA(dev)->callback = NULL;
287 
288 	if (clock_control_on(clk, (clock_control_subsys_t *) &cfg->pclken) != 0) {
289 		LOG_ERR("clock op failed\n");
290 		return -EIO;
291 	}
292 
293 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
294 
295 	LL_PWR_EnableBkUpAccess();
296 
297 #if defined(CONFIG_COUNTER_RTC_STM32_BACKUP_DOMAIN_RESET)
298 	LL_RCC_ForceBackupDomainReset();
299 	LL_RCC_ReleaseBackupDomainReset();
300 #endif
301 
302 #if defined(CONFIG_COUNTER_RTC_STM32_CLOCK_LSI)
303 
304 #if defined(CONFIG_SOC_SERIES_STM32WBX)
305 	LL_RCC_LSI1_Enable();
306 	while (LL_RCC_LSI1_IsReady() != 1) {
307 	}
308 #else
309 	LL_RCC_LSI_Enable();
310 	while (LL_RCC_LSI_IsReady() != 1) {
311 	}
312 #endif /* CONFIG_SOC_SERIES_STM32WBX */
313 
314 	LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);
315 
316 #else /* CONFIG_COUNTER_RTC_STM32_CLOCK_LSE */
317 
318 #if !defined(CONFIG_SOC_SERIES_STM32F4X) &&	\
319 	!defined(CONFIG_SOC_SERIES_STM32F2X) && \
320 	!defined(CONFIG_SOC_SERIES_STM32L1X)
321 
322 	LL_RCC_LSE_SetDriveCapability(
323 		CONFIG_COUNTER_RTC_STM32_LSE_DRIVE_STRENGTH);
324 
325 #endif /*
326 	* !CONFIG_SOC_SERIES_STM32F4X
327 	* && !CONFIG_SOC_SERIES_STM32F2X
328 	* && !CONFIG_SOC_SERIES_STM32L1X
329 	*/
330 
331 #if defined(CONFIG_COUNTER_RTC_STM32_LSE_BYPASS)
332 	LL_RCC_LSE_EnableBypass();
333 #endif /* CONFIG_COUNTER_RTC_STM32_LSE_BYPASS */
334 
335 	LL_RCC_LSE_Enable();
336 
337 	/* Wait until LSE is ready */
338 	while (LL_RCC_LSE_IsReady() != 1) {
339 	}
340 
341 #if STM32_MSI_PLL_MODE
342 	/* Enable MSI hardware auto calibration */
343 	LL_RCC_MSI_EnablePLLMode();
344 #endif
345 
346 	LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
347 
348 #endif /* CONFIG_COUNTER_RTC_STM32_CLOCK_SRC */
349 
350 	LL_RCC_EnableRTC();
351 
352 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
353 
354 #if !defined(CONFIG_COUNTER_RTC_STM32_SAVE_VALUE_BETWEEN_RESETS)
355 	if (LL_RTC_DeInit(RTC) != SUCCESS) {
356 		return -EIO;
357 	}
358 #endif
359 
360 	if (LL_RTC_Init(RTC, ((LL_RTC_InitTypeDef *)
361 			      &cfg->ll_rtc_config)) != SUCCESS) {
362 		return -EIO;
363 	}
364 
365 #ifdef RTC_CR_BYPSHAD
366 	LL_RTC_DisableWriteProtection(RTC);
367 	LL_RTC_EnableShadowRegBypass(RTC);
368 	LL_RTC_EnableWriteProtection(RTC);
369 #endif /* RTC_CR_BYPSHAD */
370 
371 #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
372 	LL_C2_EXTI_EnableIT_0_31(RTC_EXTI_LINE);
373 #else
374 	LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE);
375 #endif
376 	LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE);
377 
378 	rtc_stm32_irq_config(dev);
379 
380 	return 0;
381 }
382 
383 static struct rtc_stm32_data rtc_data;
384 
385 static const struct rtc_stm32_config rtc_config = {
386 	.counter_info = {
387 		.max_top_value = UINT32_MAX,
388 		.freq = 1,
389 		.flags = COUNTER_CONFIG_INFO_COUNT_UP,
390 		.channels = 1,
391 	},
392 	.pclken = {
393 		.enr = DT_INST_CLOCKS_CELL(0, bits),
394 		.bus = DT_INST_CLOCKS_CELL(0, bus),
395 	},
396 	.ll_rtc_config = {
397 		.HourFormat = LL_RTC_HOURFORMAT_24HOUR,
398 #if defined(CONFIG_COUNTER_RTC_STM32_CLOCK_LSI)
399 		/* prescaler values for LSI @ 32 KHz */
400 		.AsynchPrescaler = 0x7F,
401 		.SynchPrescaler = 0x00F9,
402 #else /* CONFIG_COUNTER_RTC_STM32_CLOCK_LSE */
403 		/* prescaler values for LSE @ 32768 Hz */
404 		.AsynchPrescaler = 0x7F,
405 		.SynchPrescaler = 0x00FF,
406 #endif
407 	},
408 };
409 
410 
411 static const struct counter_driver_api rtc_stm32_driver_api = {
412 		.start = rtc_stm32_start,
413 		.stop = rtc_stm32_stop,
414 		.get_value = rtc_stm32_get_value,
415 		.set_alarm = rtc_stm32_set_alarm,
416 		.cancel_alarm = rtc_stm32_cancel_alarm,
417 		.set_top_value = rtc_stm32_set_top_value,
418 		.get_pending_int = rtc_stm32_get_pending_int,
419 		.get_top_value = rtc_stm32_get_top_value,
420 };
421 
422 DEVICE_DT_INST_DEFINE(0, &rtc_stm32_init, NULL,
423 		    &rtc_data, &rtc_config, PRE_KERNEL_1,
424 		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &rtc_stm32_driver_api);
425 
rtc_stm32_irq_config(const struct device * dev)426 static void rtc_stm32_irq_config(const struct device *dev)
427 {
428 	IRQ_CONNECT(DT_INST_IRQN(0),
429 		    DT_INST_IRQ(0, priority),
430 		    rtc_stm32_isr, DEVICE_DT_INST_GET(0), 0);
431 	irq_enable(DT_INST_IRQN(0));
432 }
433