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