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