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