1 /*
2 * Copyright (c) 2023 Trackunit Corporation
3 * Copyright (c) 2023 Bjarki Arge Andreasen
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @file drivers/rtc.h
10 * @brief Public real time clock driver API
11 */
12
13 #ifndef ZEPHYR_INCLUDE_DRIVERS_RTC_H_
14 #define ZEPHYR_INCLUDE_DRIVERS_RTC_H_
15
16 /**
17 * @brief RTC Interface
18 * @defgroup rtc_interface RTC Interface
19 * @since 3.4
20 * @version 0.1.0
21 * @ingroup io_interfaces
22 * @{
23 */
24
25 #include <zephyr/kernel.h>
26 #include <zephyr/device.h>
27 #include <errno.h>
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 /**
34 * @brief Mask for alarm time fields to enable when setting alarm time
35 * @name RTC Alarm Time Mask
36 * @anchor RTC_ALARM_TIME_MASK
37 * @{
38 */
39 #define RTC_ALARM_TIME_MASK_SECOND BIT(0)
40 #define RTC_ALARM_TIME_MASK_MINUTE BIT(1)
41 #define RTC_ALARM_TIME_MASK_HOUR BIT(2)
42 #define RTC_ALARM_TIME_MASK_MONTHDAY BIT(3)
43 #define RTC_ALARM_TIME_MASK_MONTH BIT(4)
44 #define RTC_ALARM_TIME_MASK_YEAR BIT(5)
45 #define RTC_ALARM_TIME_MASK_WEEKDAY BIT(6)
46 #define RTC_ALARM_TIME_MASK_YEARDAY BIT(7)
47 #define RTC_ALARM_TIME_MASK_NSEC BIT(8)
48 /**
49 * @}
50 */
51
52 /**
53 * @brief Structure for storing date and time values with sub-second precision.
54 *
55 * @details The structure is 1-1 mapped to the struct tm for the members
56 * \p tm_sec to \p tm_isdst making it compatible with the standard time library.
57 *
58 * @note Use \ref rtc_time_to_tm() to safely cast from a \ref rtc_time
59 * pointer to a \ref tm pointer.
60 */
61 struct rtc_time {
62 int tm_sec; /**< Seconds [0, 59] */
63 int tm_min; /**< Minutes [0, 59] */
64 int tm_hour; /**< Hours [0, 23] */
65 int tm_mday; /**< Day of the month [1, 31] */
66 int tm_mon; /**< Month [0, 11] */
67 int tm_year; /**< Year - 1900 */
68 int tm_wday; /**< Day of the week [0, 6] (Sunday = 0) (Unknown = -1) */
69 int tm_yday; /**< Day of the year [0, 365] (Unknown = -1) */
70 int tm_isdst; /**< Daylight saving time flag [-1] (Unknown = -1) */
71 int tm_nsec; /**< Nanoseconds [0, 999999999] (Unknown = 0) */
72 };
73
74 /**
75 * @typedef rtc_update_callback
76 * @brief RTC update event callback
77 *
78 * @param dev Device instance invoking the handler
79 * @param user_data Optional user data provided when update irq callback is set
80 */
81 typedef void (*rtc_update_callback)(const struct device *dev, void *user_data);
82
83 /**
84 * @typedef rtc_alarm_callback
85 * @brief RTC alarm triggered callback
86 *
87 * @param dev Device instance invoking the handler
88 * @param id Alarm id
89 * @param user_data Optional user data passed with the alarm configuration
90 */
91 typedef void (*rtc_alarm_callback)(const struct device *dev, uint16_t id, void *user_data);
92
93 /**
94 * @cond INTERNAL_HIDDEN
95 *
96 * For internal driver use only, skip these in public documentation.
97 */
98
99 /**
100 * @typedef rtc_api_set_time
101 * @brief API for setting RTC time
102 */
103 typedef int (*rtc_api_set_time)(const struct device *dev, const struct rtc_time *timeptr);
104
105 /**
106 * @typedef rtc_api_get_time
107 * @brief API for getting RTC time
108 */
109 typedef int (*rtc_api_get_time)(const struct device *dev, struct rtc_time *timeptr);
110
111 /**
112 * @typedef rtc_api_alarm_get_supported_fields
113 * @brief API for getting the supported fields of the RTC alarm time
114 */
115 typedef int (*rtc_api_alarm_get_supported_fields)(const struct device *dev, uint16_t id,
116 uint16_t *mask);
117
118 /**
119 * @typedef rtc_api_alarm_set_time
120 * @brief API for setting RTC alarm time
121 */
122 typedef int (*rtc_api_alarm_set_time)(const struct device *dev, uint16_t id, uint16_t mask,
123 const struct rtc_time *timeptr);
124
125 /**
126 * @typedef rtc_api_alarm_get_time
127 * @brief API for getting RTC alarm time
128 */
129 typedef int (*rtc_api_alarm_get_time)(const struct device *dev, uint16_t id, uint16_t *mask,
130 struct rtc_time *timeptr);
131
132 /**
133 * @typedef rtc_api_alarm_is_pending
134 * @brief API for testing if RTC alarm is pending
135 */
136 typedef int (*rtc_api_alarm_is_pending)(const struct device *dev, uint16_t id);
137
138 /**
139 * @typedef rtc_api_alarm_set_callback
140 * @brief API for setting RTC alarm callback
141 */
142 typedef int (*rtc_api_alarm_set_callback)(const struct device *dev, uint16_t id,
143 rtc_alarm_callback callback, void *user_data);
144
145 /**
146 * @typedef rtc_api_update_set_callback
147 * @brief API for setting RTC update callback
148 */
149 typedef int (*rtc_api_update_set_callback)(const struct device *dev,
150 rtc_update_callback callback, void *user_data);
151
152 /**
153 * @typedef rtc_api_set_calibration
154 * @brief API for setting RTC calibration
155 */
156 typedef int (*rtc_api_set_calibration)(const struct device *dev, int32_t calibration);
157
158 /**
159 * @typedef rtc_api_get_calibration
160 * @brief API for getting RTC calibration
161 */
162 typedef int (*rtc_api_get_calibration)(const struct device *dev, int32_t *calibration);
163
164 /**
165 * @brief RTC driver API
166 */
167 __subsystem struct rtc_driver_api {
168 rtc_api_set_time set_time;
169 rtc_api_get_time get_time;
170 #if defined(CONFIG_RTC_ALARM) || defined(__DOXYGEN__)
171 rtc_api_alarm_get_supported_fields alarm_get_supported_fields;
172 rtc_api_alarm_set_time alarm_set_time;
173 rtc_api_alarm_get_time alarm_get_time;
174 rtc_api_alarm_is_pending alarm_is_pending;
175 rtc_api_alarm_set_callback alarm_set_callback;
176 #endif /* CONFIG_RTC_ALARM */
177 #if defined(CONFIG_RTC_UPDATE) || defined(__DOXYGEN__)
178 rtc_api_update_set_callback update_set_callback;
179 #endif /* CONFIG_RTC_UPDATE */
180 #if defined(CONFIG_RTC_CALIBRATION) || defined(__DOXYGEN__)
181 rtc_api_set_calibration set_calibration;
182 rtc_api_get_calibration get_calibration;
183 #endif /* CONFIG_RTC_CALIBRATION */
184 };
185
186 /** @endcond */
187
188 /**
189 * @brief API for setting RTC time.
190 *
191 * @param dev Device instance
192 * @param timeptr The time to set
193 *
194 * @return 0 if successful
195 * @return -EINVAL if RTC time is invalid or exceeds hardware capabilities
196 * @return -errno code if failure
197 */
198 __syscall int rtc_set_time(const struct device *dev, const struct rtc_time *timeptr);
199
z_impl_rtc_set_time(const struct device * dev,const struct rtc_time * timeptr)200 static inline int z_impl_rtc_set_time(const struct device *dev, const struct rtc_time *timeptr)
201 {
202 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
203
204 return api->set_time(dev, timeptr);
205 }
206
207 /**
208 * @brief API for getting RTC time.
209 *
210 * @param dev Device instance
211 * @param timeptr Destination for the time
212 *
213 * @return 0 if successful
214 * @return -ENODATA if RTC time has not been set
215 * @return -errno code if failure
216 */
217 __syscall int rtc_get_time(const struct device *dev, struct rtc_time *timeptr);
218
z_impl_rtc_get_time(const struct device * dev,struct rtc_time * timeptr)219 static inline int z_impl_rtc_get_time(const struct device *dev, struct rtc_time *timeptr)
220 {
221 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
222
223 return api->get_time(dev, timeptr);
224 }
225
226 /**
227 * @name RTC Interface Alarm
228 * @{
229 */
230 #if defined(CONFIG_RTC_ALARM) || defined(__DOXYGEN__)
231
232 /**
233 * @brief API for getting the supported fields of the RTC alarm time.
234 *
235 * @param dev Device instance
236 * @param id Id of the alarm
237 * @param mask Mask of fields in the alarm time which are supported
238 *
239 * @note Bits in the mask param are defined here @ref RTC_ALARM_TIME_MASK.
240 *
241 * @return 0 if successful
242 * @return -EINVAL if id is out of range or time is invalid
243 * @return -ENOTSUP if API is not supported by hardware
244 * @return -errno code if failure
245 */
246 __syscall int rtc_alarm_get_supported_fields(const struct device *dev, uint16_t id,
247 uint16_t *mask);
248
z_impl_rtc_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)249 static inline int z_impl_rtc_alarm_get_supported_fields(const struct device *dev, uint16_t id,
250 uint16_t *mask)
251 {
252 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
253
254 if (api->alarm_get_supported_fields == NULL) {
255 return -ENOSYS;
256 }
257
258 return api->alarm_get_supported_fields(dev, id, mask);
259 }
260
261 /**
262 * @brief API for setting RTC alarm time.
263 *
264 * @details To enable an RTC alarm, one or more fields of the RTC alarm time
265 * must be enabled. The mask designates which fields of the RTC alarm time to
266 * enable. If the mask parameter is 0, the alarm will be disabled. The RTC
267 * alarm will trigger when all enabled fields of the alarm time match the RTC
268 * time.
269 *
270 * @param dev Device instance
271 * @param id Id of the alarm
272 * @param mask Mask of fields in the alarm time to enable
273 * @param timeptr The alarm time to set
274 *
275 * @note The timeptr param may be NULL if the mask param is 0
276 * @note Only the enabled fields in the timeptr param need to be configured
277 * @note Bits in the mask param are defined here @ref RTC_ALARM_TIME_MASK
278 *
279 * @return 0 if successful
280 * @return -EINVAL if id is out of range or time is invalid
281 * @return -ENOTSUP if API is not supported by hardware
282 * @return -errno code if failure
283 */
284 __syscall int rtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
285 const struct rtc_time *timeptr);
286
z_impl_rtc_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)287 static inline int z_impl_rtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
288 const struct rtc_time *timeptr)
289 {
290 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
291
292 if (api->alarm_set_time == NULL) {
293 return -ENOSYS;
294 }
295
296 return api->alarm_set_time(dev, id, mask, timeptr);
297 }
298
299 /**
300 * @brief API for getting RTC alarm time.
301 *
302 * @param dev Device instance
303 * @param id Id of the alarm
304 * @param mask Destination for mask of fields which are enabled in the alarm time
305 * @param timeptr Destination for the alarm time
306 *
307 * @note Bits in the mask param are defined here @ref RTC_ALARM_TIME_MASK
308 *
309 * @return 0 if successful
310 * @return -EINVAL if id is out of range
311 * @return -ENOTSUP if API is not supported by hardware
312 * @return -errno code if failure
313 */
314 __syscall int rtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
315 struct rtc_time *timeptr);
316
z_impl_rtc_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)317 static inline int z_impl_rtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
318 struct rtc_time *timeptr)
319 {
320 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
321
322 if (api->alarm_get_time == NULL) {
323 return -ENOSYS;
324 }
325
326 return api->alarm_get_time(dev, id, mask, timeptr);
327 }
328
329 /**
330 * @brief API for testing if RTC alarm is pending.
331 *
332 * @details Test whether or not the alarm with id is pending. If the alarm
333 * is pending, the pending status is cleared.
334 *
335 * @param dev Device instance
336 * @param id Id of the alarm to test
337 *
338 * @return 1 if alarm was pending
339 * @return 0 if alarm was not pending
340 * @return -EINVAL if id is out of range
341 * @return -ENOTSUP if API is not supported by hardware
342 * @return -errno code if failure
343 */
344 __syscall int rtc_alarm_is_pending(const struct device *dev, uint16_t id);
345
z_impl_rtc_alarm_is_pending(const struct device * dev,uint16_t id)346 static inline int z_impl_rtc_alarm_is_pending(const struct device *dev, uint16_t id)
347 {
348 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
349
350 if (api->alarm_is_pending == NULL) {
351 return -ENOSYS;
352 }
353
354 return api->alarm_is_pending(dev, id);
355 }
356
357 /**
358 * @brief API for setting alarm callback.
359 *
360 * @details Setting the alarm callback for an alarm, will enable the
361 * alarm callback. When the callback for an alarm is enabled, the
362 * alarm triggered event will invoke the callback, after which the
363 * alarm pending status will be cleared automatically. The alarm will
364 * remain enabled until manually disabled using
365 * \ref rtc_alarm_set_time().
366 *
367 * To disable the alarm callback for an alarm, the \p callback and
368 * \p user_data parameters must be set to NULL. When the alarm
369 * callback for an alarm is disabled, the alarm triggered event will
370 * set the alarm status to "pending". To check if the alarm status is
371 * "pending", use \ref rtc_alarm_is_pending().
372 *
373 * @param dev Device instance
374 * @param id Id of the alarm for which the callback shall be set
375 * @param callback Callback called when alarm occurs
376 * @param user_data Optional user data passed to callback
377 *
378 * @return 0 if successful
379 * @return -EINVAL if id is out of range
380 * @return -ENOTSUP if API is not supported by hardware
381 * @return -errno code if failure
382 */
383 __syscall int rtc_alarm_set_callback(const struct device *dev, uint16_t id,
384 rtc_alarm_callback callback, void *user_data);
385
z_impl_rtc_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)386 static inline int z_impl_rtc_alarm_set_callback(const struct device *dev, uint16_t id,
387 rtc_alarm_callback callback, void *user_data)
388 {
389 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
390
391 if (api->alarm_set_callback == NULL) {
392 return -ENOSYS;
393 }
394
395 return api->alarm_set_callback(dev, id, callback, user_data);
396 }
397
398 #endif /* CONFIG_RTC_ALARM */
399 /**
400 * @}
401 */
402
403 /**
404 * @name RTC Interface Update
405 * @{
406 */
407 #if defined(CONFIG_RTC_UPDATE) || defined(__DOXYGEN__)
408
409 /**
410 * @brief API for setting update callback.
411 *
412 * @details Setting the update callback will enable the update
413 * callback. The update callback will be invoked every time the
414 * RTC clock is updated by 1 second. It can be used to
415 * synchronize the RTC clock with other clock sources.
416 *
417 * To disable the update callback for the RTC clock, the
418 * \p callback and \p user_data parameters must be set to NULL.
419 *
420 * @param dev Device instance
421 * @param callback Callback called when update occurs
422 * @param user_data Optional user data passed to callback
423 *
424 * @return 0 if successful
425 * @return -ENOTSUP if API is not supported by hardware
426 * @return -errno code if failure
427 */
428 __syscall int rtc_update_set_callback(const struct device *dev, rtc_update_callback callback,
429 void *user_data);
430
z_impl_rtc_update_set_callback(const struct device * dev,rtc_update_callback callback,void * user_data)431 static inline int z_impl_rtc_update_set_callback(const struct device *dev,
432 rtc_update_callback callback, void *user_data)
433 {
434 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
435
436 if (api->update_set_callback == NULL) {
437 return -ENOSYS;
438 }
439
440 return api->update_set_callback(dev, callback, user_data);
441 }
442
443 #endif /* CONFIG_RTC_UPDATE */
444 /**
445 * @}
446 */
447
448 /**
449 * @name RTC Interface Calibration
450 * @{
451 */
452 #if defined(CONFIG_RTC_CALIBRATION) || defined(__DOXYGEN__)
453
454 /**
455 * @brief API for setting RTC calibration.
456 *
457 * @details Calibration is applied to the RTC clock input. A
458 * positive calibration value will increase the frequency of
459 * the RTC clock, a negative value will decrease the
460 * frequency of the RTC clock.
461 *
462 * @see rtc_calibration_from_frequency()
463 *
464 * @param dev Device instance
465 * @param calibration Calibration to set in parts per billion
466 *
467 * @return 0 if successful
468 * @return -EINVAL if calibration is out of range
469 * @return -ENOTSUP if API is not supported by hardware
470 * @return -errno code if failure
471 */
472 __syscall int rtc_set_calibration(const struct device *dev, int32_t calibration);
473
z_impl_rtc_set_calibration(const struct device * dev,int32_t calibration)474 static inline int z_impl_rtc_set_calibration(const struct device *dev, int32_t calibration)
475 {
476 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
477
478 if (api->set_calibration == NULL) {
479 return -ENOSYS;
480 }
481
482 return api->set_calibration(dev, calibration);
483 }
484
485 /**
486 * @brief API for getting RTC calibration.
487 *
488 * @param dev Device instance
489 * @param calibration Destination for calibration in parts per billion
490 *
491 * @return 0 if successful
492 * @return -ENOTSUP if API is not supported by hardware
493 * @return -errno code if failure
494 */
495 __syscall int rtc_get_calibration(const struct device *dev, int32_t *calibration);
496
z_impl_rtc_get_calibration(const struct device * dev,int32_t * calibration)497 static inline int z_impl_rtc_get_calibration(const struct device *dev, int32_t *calibration)
498 {
499 const struct rtc_driver_api *api = (const struct rtc_driver_api *)dev->api;
500
501 if (api->get_calibration == NULL) {
502 return -ENOSYS;
503 }
504
505 return api->get_calibration(dev, calibration);
506 }
507
508 #endif /* CONFIG_RTC_CALIBRATION */
509 /**
510 * @}
511 */
512
513 /**
514 * @name RTC Interface Helpers
515 * @{
516 */
517
518 /**
519 * @brief Forward declaration of struct tm for \ref rtc_time_to_tm().
520 */
521 struct tm;
522
523 /**
524 * @brief Convenience function for safely casting a \ref rtc_time pointer
525 * to a \ref tm pointer.
526 */
rtc_time_to_tm(struct rtc_time * timeptr)527 static inline struct tm *rtc_time_to_tm(struct rtc_time *timeptr)
528 {
529 return (struct tm *)timeptr;
530 }
531
532 /**
533 * @brief Determine required calibration to 1 Hertz from frequency.
534 *
535 * @param frequency Frequency of the RTC in nano Hertz
536 *
537 * @return The required calibration in parts per billion
538 */
rtc_calibration_from_frequency(uint32_t frequency)539 static inline int32_t rtc_calibration_from_frequency(uint32_t frequency)
540 {
541 __ASSERT_NO_MSG(frequency > 0);
542
543 return (int32_t)((1000000000000000000LL / frequency) - 1000000000);
544 }
545
546 /**
547 * @}
548 */
549
550 /**
551 * @}
552 */
553
554 #ifdef __cplusplus
555 }
556 #endif
557
558 #include <zephyr/syscalls/rtc.h>
559
560 #endif /* ZEPHYR_INCLUDE_DRIVERS_RTC_H_ */
561