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