1 /*
2 * Copyright (c) 2023 Prevas A/S
3 * Copyright (c) 2023 Syslinbit
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 */
8
9 #define DT_DRV_COMPAT st_stm32_rtc
10
11 #include <errno.h>
12 #include <zephyr/device.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/init.h>
15 #include <zephyr/devicetree.h>
16 #include <zephyr/drivers/rtc.h>
17 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
18 #include <zephyr/drivers/clock_control.h>
19 #include <zephyr/sys/util.h>
20 #include <soc.h>
21 #include <stm32_ll_pwr.h>
22 #include <stm32_ll_rcc.h>
23 #include <stm32_ll_rtc.h>
24 #include <stm32_hsem.h>
25
26 #include <zephyr/logging/log.h>
27
28 #include <stdbool.h>
29
30 LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL);
31
32 #if defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SUBSECOND_SUPPORT)
33 /* subsecond counting is not supported by some STM32L1x MCUs */
34 #define HW_SUBSECOND_SUPPORT (0)
35 #else
36 #define HW_SUBSECOND_SUPPORT (1)
37 #endif
38
39 /* RTC start time: 1st, Jan, 2000 */
40 #define RTC_YEAR_REF 2000
41 /* struct tm start time: 1st, Jan, 1900 */
42 #define TM_YEAR_REF 1900
43
44 /* Convert part per billion calibration value to a number of clock pulses added or removed each
45 * 2^20 clock cycles so it is suitable for the CALR register fields
46 *
47 * nb_pulses = ppb * 2^20 / 10^9 = ppb * 2^11 / 5^9 = ppb * 2048 / 1953125
48 */
49 #define PPB_TO_NB_PULSES(ppb) DIV_ROUND_CLOSEST((ppb) * 2048, 1953125)
50
51 /* Convert CALR register value (number of clock pulses added or removed each 2^20 clock cycles)
52 * to part ber billion calibration value
53 *
54 * ppb = nb_pulses * 10^9 / 2^20 = nb_pulses * 5^9 / 2^11 = nb_pulses * 1953125 / 2048
55 */
56 #define NB_PULSES_TO_PPB(pulses) DIV_ROUND_CLOSEST((pulses) * 1953125, 2048)
57
58 /* CALP field can only be 512 or 0 as in reality CALP is a single bit field representing 512 pulses
59 * added every 2^20 clock cycles
60 */
61 #define MAX_CALP (512)
62 #define MAX_CALM (511)
63
64 #define MAX_PPB NB_PULSES_TO_PPB(MAX_CALP)
65 #define MIN_PPB -NB_PULSES_TO_PPB(MAX_CALM)
66
67 /* Timeout in microseconds used to wait for flags */
68 #define RTC_TIMEOUT 1000000
69
70 struct rtc_stm32_config {
71 uint32_t async_prescaler;
72 uint32_t sync_prescaler;
73 const struct stm32_pclken *pclken;
74 };
75
76 struct rtc_stm32_data {
77 struct k_mutex lock;
78 };
79
rtc_stm32_enter_initialization_mode(bool kernel_available)80 static int rtc_stm32_enter_initialization_mode(bool kernel_available)
81 {
82 if (kernel_available) {
83 LL_RTC_EnableInitMode(RTC);
84 bool success = WAIT_FOR(LL_RTC_IsActiveFlag_INIT(RTC), RTC_TIMEOUT, k_msleep(1));
85
86 if (!success) {
87 return -EIO;
88 }
89 } else {
90 /* kernel is not available so use the blocking but otherwise equivalent function
91 * provided by LL
92 */
93 ErrorStatus status = LL_RTC_EnterInitMode(RTC);
94
95 if (status != SUCCESS) {
96 return -EIO;
97 }
98 }
99
100 return 0;
101 }
102
rtc_stm32_leave_initialization_mode(void)103 static inline void rtc_stm32_leave_initialization_mode(void)
104 {
105 LL_RTC_DisableInitMode(RTC);
106 }
107
rtc_stm32_configure(const struct device * dev)108 static int rtc_stm32_configure(const struct device *dev)
109 {
110 const struct rtc_stm32_config *cfg = dev->config;
111
112 int err = 0;
113
114 uint32_t hour_format = LL_RTC_GetHourFormat(RTC);
115 uint32_t sync_prescaler = LL_RTC_GetSynchPrescaler(RTC);
116 uint32_t async_prescaler = LL_RTC_GetAsynchPrescaler(RTC);
117
118 LL_RTC_DisableWriteProtection(RTC);
119
120 /* configuration process requires to stop the RTC counter so do it
121 * only if needed to avoid inducing time drift at each reset
122 */
123 if ((hour_format != LL_RTC_HOURFORMAT_24HOUR) ||
124 (sync_prescaler != cfg->sync_prescaler) ||
125 (async_prescaler != cfg->async_prescaler)) {
126 err = rtc_stm32_enter_initialization_mode(false);
127 if (err == 0) {
128 LL_RTC_SetHourFormat(RTC, LL_RTC_HOURFORMAT_24HOUR);
129 LL_RTC_SetSynchPrescaler(RTC, cfg->sync_prescaler);
130 LL_RTC_SetAsynchPrescaler(RTC, cfg->async_prescaler);
131 }
132
133 rtc_stm32_leave_initialization_mode();
134 }
135
136 #ifdef RTC_CR_BYPSHAD
137 LL_RTC_EnableShadowRegBypass(RTC);
138 #endif /* RTC_CR_BYPSHAD */
139
140 LL_RTC_EnableWriteProtection(RTC);
141
142 return err;
143 }
144
rtc_stm32_init(const struct device * dev)145 static int rtc_stm32_init(const struct device *dev)
146 {
147 const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
148 const struct rtc_stm32_config *cfg = dev->config;
149 struct rtc_stm32_data *data = dev->data;
150
151 int err = 0;
152
153 if (!device_is_ready(clk)) {
154 LOG_ERR("clock control device not ready");
155 return -ENODEV;
156 }
157
158 /* Enable RTC bus clock */
159 if (clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken[0]) != 0) {
160 LOG_ERR("clock op failed\n");
161 return -EIO;
162 }
163
164 k_mutex_init(&data->lock);
165
166 /* Enable Backup access */
167 z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
168 #if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP)
169 LL_PWR_EnableBkUpAccess();
170 #endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */
171
172 /* Enable RTC clock source */
173 if (clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL) != 0) {
174 LOG_ERR("clock configure failed\n");
175 return -EIO;
176 }
177
178 LL_RCC_EnableRTC();
179
180 z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
181
182 err = rtc_stm32_configure(dev);
183
184 return err;
185 }
186
rtc_stm32_set_time(const struct device * dev,const struct rtc_time * timeptr)187 static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr)
188 {
189 struct rtc_stm32_data *data = dev->data;
190
191 uint32_t real_year = timeptr->tm_year + TM_YEAR_REF;
192
193 int err = 0;
194
195 if (real_year < RTC_YEAR_REF) {
196 /* RTC does not support years before 2000 */
197 return -EINVAL;
198 }
199
200 if (timeptr->tm_wday == -1) {
201 /* day of the week is expected */
202 return -EINVAL;
203 }
204
205 err = k_mutex_lock(&data->lock, K_NO_WAIT);
206 if (err) {
207 return err;
208 }
209
210 LOG_INF("Setting clock");
211 LL_RTC_DisableWriteProtection(RTC);
212
213 err = rtc_stm32_enter_initialization_mode(true);
214 if (err) {
215 k_mutex_unlock(&data->lock);
216 return err;
217 }
218
219 LL_RTC_DATE_SetYear(RTC, bin2bcd(real_year - RTC_YEAR_REF));
220 LL_RTC_DATE_SetMonth(RTC, bin2bcd(timeptr->tm_mon + 1));
221 LL_RTC_DATE_SetDay(RTC, bin2bcd(timeptr->tm_mday));
222
223 if (timeptr->tm_wday == 0) {
224 /* sunday (tm_wday = 0) is not represented by the same value in hardware */
225 LL_RTC_DATE_SetWeekDay(RTC, LL_RTC_WEEKDAY_SUNDAY);
226 } else {
227 /* all the other values are consistent with what is expected by hardware */
228 LL_RTC_DATE_SetWeekDay(RTC, timeptr->tm_wday);
229 }
230
231
232 LL_RTC_TIME_SetHour(RTC, bin2bcd(timeptr->tm_hour));
233 LL_RTC_TIME_SetMinute(RTC, bin2bcd(timeptr->tm_min));
234 LL_RTC_TIME_SetSecond(RTC, bin2bcd(timeptr->tm_sec));
235
236 rtc_stm32_leave_initialization_mode();
237
238 LL_RTC_EnableWriteProtection(RTC);
239
240 k_mutex_unlock(&data->lock);
241
242 return err;
243 }
244
rtc_stm32_get_time(const struct device * dev,struct rtc_time * timeptr)245 static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr)
246 {
247 struct rtc_stm32_data *data = dev->data;
248
249 uint32_t rtc_date, rtc_time;
250
251 #if HW_SUBSECOND_SUPPORT
252 const struct rtc_stm32_config *cfg = dev->config;
253 uint32_t rtc_subsecond;
254 #endif
255
256 int err = k_mutex_lock(&data->lock, K_NO_WAIT);
257
258 if (err) {
259 return err;
260 }
261
262 do {
263 /* read date, time and subseconds and relaunch if a day increment occurred
264 * while doing so as it will result in an erroneous result otherwise
265 */
266 rtc_date = LL_RTC_DATE_Get(RTC);
267 do {
268 /* read time and subseconds and relaunch if a second increment occurred
269 * while doing so as it will result in an erroneous result otherwise
270 */
271 rtc_time = LL_RTC_TIME_Get(RTC);
272 #if HW_SUBSECOND_SUPPORT
273 rtc_subsecond = LL_RTC_TIME_GetSubSecond(RTC);
274 #endif
275 } while (rtc_time != LL_RTC_TIME_Get(RTC));
276 } while (rtc_date != LL_RTC_DATE_Get(RTC));
277
278 k_mutex_unlock(&data->lock);
279
280 timeptr->tm_year = bcd2bin(__LL_RTC_GET_YEAR(rtc_date)) + RTC_YEAR_REF - TM_YEAR_REF;
281 /* tm_mon allowed values are 0-11 */
282 timeptr->tm_mon = bcd2bin(__LL_RTC_GET_MONTH(rtc_date)) - 1;
283 timeptr->tm_mday = bcd2bin(__LL_RTC_GET_DAY(rtc_date));
284
285 int hw_wday = __LL_RTC_GET_WEEKDAY(rtc_date);
286
287 if (hw_wday == LL_RTC_WEEKDAY_SUNDAY) {
288 /* LL_RTC_WEEKDAY_SUNDAY = 7 but a 0 is expected in tm_wday for sunday */
289 timeptr->tm_wday = 0;
290 } else {
291 /* all other values are consistent between hardware and rtc_time structure */
292 timeptr->tm_wday = hw_wday;
293 }
294
295 timeptr->tm_hour = bcd2bin(__LL_RTC_GET_HOUR(rtc_time));
296 timeptr->tm_min = bcd2bin(__LL_RTC_GET_MINUTE(rtc_time));
297 timeptr->tm_sec = bcd2bin(__LL_RTC_GET_SECOND(rtc_time));
298
299 #if HW_SUBSECOND_SUPPORT
300 uint64_t temp = ((uint64_t)(cfg->sync_prescaler - rtc_subsecond)) * 1000000000L;
301
302 timeptr->tm_nsec = DIV_ROUND_CLOSEST(temp, cfg->sync_prescaler + 1);
303 #else
304 timeptr->tm_nsec = 0;
305 #endif
306
307 /* unknown values */
308 timeptr->tm_yday = -1;
309 timeptr->tm_isdst = -1;
310
311 return 0;
312 }
313
314 #ifdef CONFIG_RTC_CALIBRATION
315 #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \
316 !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT))
rtc_stm32_set_calibration(const struct device * dev,int32_t calibration)317 static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibration)
318 {
319 ARG_UNUSED(dev);
320
321 /* Note : calibration is considered here to be ppb value to apply
322 * on clock period (not frequency) but with an opposite sign
323 */
324
325 if ((calibration > MAX_PPB) || (calibration < MIN_PPB)) {
326 /* out of supported range */
327 return -EINVAL;
328 }
329
330 int32_t nb_pulses = PPB_TO_NB_PULSES(calibration);
331
332 /* we tested calibration against supported range
333 * so theoretically nb_pulses is also within range
334 */
335 __ASSERT_NO_MSG(nb_pulses <= MAX_CALP);
336 __ASSERT_NO_MSG(nb_pulses >= -MAX_CALM);
337
338 uint32_t calp, calm;
339
340 if (nb_pulses > 0) {
341 calp = LL_RTC_CALIB_INSERTPULSE_SET;
342 calm = MAX_CALP - nb_pulses;
343 } else {
344 calp = LL_RTC_CALIB_INSERTPULSE_NONE;
345 calm = -nb_pulses;
346 }
347
348 /* wait for recalibration to be ok if a previous recalibration occurred */
349 if (!WAIT_FOR(LL_RTC_IsActiveFlag_RECALP(RTC) == 0, 100000, k_msleep(1))) {
350 return -EIO;
351 }
352
353 LL_RTC_DisableWriteProtection(RTC);
354
355 MODIFY_REG(RTC->CALR, RTC_CALR_CALP | RTC_CALR_CALM, calp | calm);
356
357 LL_RTC_EnableWriteProtection(RTC);
358
359 return 0;
360 }
361
rtc_stm32_get_calibration(const struct device * dev,int32_t * calibration)362 static int rtc_stm32_get_calibration(const struct device *dev, int32_t *calibration)
363 {
364 ARG_UNUSED(dev);
365
366 uint32_t calr = sys_read32((mem_addr_t) &RTC->CALR);
367
368 bool calp_enabled = READ_BIT(calr, RTC_CALR_CALP);
369 uint32_t calm = READ_BIT(calr, RTC_CALR_CALM);
370
371 int32_t nb_pulses = -((int32_t) calm);
372
373 if (calp_enabled) {
374 nb_pulses += MAX_CALP;
375 }
376
377 *calibration = NB_PULSES_TO_PPB(nb_pulses);
378
379 return 0;
380 }
381 #endif
382 #endif /* CONFIG_RTC_CALIBRATION */
383
384 struct rtc_driver_api rtc_stm32_driver_api = {
385 .set_time = rtc_stm32_set_time,
386 .get_time = rtc_stm32_get_time,
387 /* RTC_ALARM not supported */
388 /* RTC_UPDATE not supported */
389 #ifdef CONFIG_RTC_CALIBRATION
390 #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \
391 !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT))
392 .set_calibration = rtc_stm32_set_calibration,
393 .get_calibration = rtc_stm32_get_calibration,
394 #else
395 #error RTC calibration for devices without smooth calibration feature is not supported yet
396 #endif
397 #endif /* CONFIG_RTC_CALIBRATION */
398 };
399
400 static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0);
401
402 BUILD_ASSERT(DT_INST_CLOCKS_HAS_IDX(0, 1), "RTC source clock not defined in the device tree");
403
404 static const struct rtc_stm32_config rtc_config = {
405 #if DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSI
406 /* prescaler values for LSI @ 32 KHz */
407 .async_prescaler = 0x7F,
408 .sync_prescaler = 0x00F9,
409 #else /* DT_INST_CLOCKS_CELL_BY_IDX(0, 1, bus) == STM32_SRC_LSE */
410 /* prescaler values for LSE @ 32768 Hz */
411 .async_prescaler = 0x7F,
412 .sync_prescaler = 0x00FF,
413 #endif
414 .pclken = rtc_clk,
415 };
416
417 static struct rtc_stm32_data rtc_data;
418
419 DEVICE_DT_INST_DEFINE(0, &rtc_stm32_init, NULL, &rtc_data, &rtc_config, PRE_KERNEL_1,
420 CONFIG_RTC_INIT_PRIORITY, &rtc_stm32_driver_api);
421