xref: /optee_os/core/include/drivers/rtc.h (revision 143e9dce8eba247521ae29c5a5fed6a7cfe3c453)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright 2022 Microchip.
4  */
5 
6 #ifndef __DRIVERS_RTC_H
7 #define __DRIVERS_RTC_H
8 
9 #include <kernel/panic.h>
10 #include <tee_api_types.h>
11 #include <util.h>
12 
13 /* The RTC allows to set/get offset for correction */
14 #define RTC_CORRECTION_FEATURE	BIT(0)
15 /* The RTC allows to set/read an alarm */
16 #define RTC_ALARM_FEATURE	BIT(1)
17 /* The RTC can wake-up the platform through alarm */
18 #define RTC_WAKEUP_ALARM	BIT(2)
19 
20 #define MS_PER_SEC		1000
21 #define MS_PER_MIN		(60 * MS_PER_SEC)
22 #define MS_PER_HOUR		(60 * MS_PER_MIN)
23 #define MS_PER_DAY		(24 * MS_PER_HOUR)
24 
25 #define RTC_TIME(year, mon, mday, wday, hour, min, sec, ms)		\
26 	{								\
27 		.tm_year = (year),					\
28 		.tm_mon = (mon),					\
29 		.tm_mday = (mday),					\
30 		.tm_wday = (wday),					\
31 		.tm_hour = (hour),					\
32 		.tm_min = (min),					\
33 		.tm_sec = (sec),					\
34 		.tm_ms = (ms),						\
35 	}
36 
37 /*
38  * struct optee_rtc_time - Time in Gregorian calendar
39  *
40  * @tm_year: Absolute year
41  * @tm_mon: Month: 0=January, 1=February, ..., 11=December
42  * @tm_mday: Month day start from 1
43  * @tm_wday: Week day: 0=Sunday, 1=Monday, ..., 6=Saturday
44  * @tm_hour: Hour in range [0 23]
45  * @tm_min: Minute in range [0 59]
46  * @tm_sec: Second in range [0 59]
47  * @tm_ms: Millisecond in range [0 999] or 0 if no applicable
48  */
49 struct optee_rtc_time {
50 	uint32_t tm_year;
51 	uint32_t tm_mon;
52 	uint32_t tm_mday;
53 	uint32_t tm_wday;
54 	uint32_t tm_hour;
55 	uint32_t tm_min;
56 	uint32_t tm_sec;
57 	uint32_t tm_ms;
58 };
59 
60 struct rtc {
61 	const struct rtc_ops *ops;
62 	struct optee_rtc_time range_min;
63 	struct optee_rtc_time range_max;
64 	bool is_wakeup_source;
65 };
66 
67 /*
68  * struct optee_rtc_alarm - The RTC alarm
69  * @enabled:		1 if the alarm is enabled, 0 otherwise
70  * @pending:		1 if the alarm is pending, 0 otherwise
71  * @time:		The alarm time
72  */
73 struct optee_rtc_alarm {
74 	bool enabled;
75 	bool pending;
76 	struct optee_rtc_time time;
77 };
78 
79 /*
80  * enum rtc_wait_alarm_status - Return status wait_alarm ops
81  * @RTC_WAIT_ALARM_RESET:		Reset the wait for the RTC alarm
82  * @RTC_WAIT_ALARM_ALARM_OCCURRED:	The RTC alarm occurred
83  * @RTC_WAIT_ALARM_CANCELED:		The wait for the RTC alarm was canceled
84  */
85 enum rtc_wait_alarm_status {
86 	RTC_WAIT_ALARM_RESET,
87 	RTC_WAIT_ALARM_ALARM_OCCURRED,
88 	RTC_WAIT_ALARM_CANCELED,
89 };
90 
91 /*
92  * struct rtc_ops - The RTC device operations
93  *
94  * @get_time:	Get the RTC time.
95  * @set_time:	Set the RTC time.
96  * @get_offset:	Get the RTC offset.
97  * @set_offset: Set the RTC offset
98  * @read_alarm:	Read the RTC alarm
99  * @set_alarm:	Set the RTC alarm
100  * @enable_alarm: Enable the RTC alarm
101  * @wait_alarm:	Wait for the RTC alarm
102  * @cancel_wait: Cancel the wait for the RTC alarm
103  * @set_alarm_wakeup_status: Set the wakeup capability of the alarm
104  */
105 struct rtc_ops {
106 	TEE_Result (*get_time)(struct rtc *rtc, struct optee_rtc_time *tm);
107 	TEE_Result (*set_time)(struct rtc *rtc, struct optee_rtc_time *tm);
108 	TEE_Result (*get_offset)(struct rtc *rtc, long *offset);
109 	TEE_Result (*set_offset)(struct rtc *rtc, long offset);
110 	TEE_Result (*read_alarm)(struct rtc *rtc, struct optee_rtc_alarm *alrm);
111 	TEE_Result (*set_alarm)(struct rtc *rtc, struct optee_rtc_alarm *alrm);
112 	TEE_Result (*enable_alarm)(struct rtc *rtc, bool enable);
113 	TEE_Result (*wait_alarm)(struct rtc *rtc,
114 				 enum rtc_wait_alarm_status *status);
115 	TEE_Result (*cancel_wait)(struct rtc *rtc);
116 	TEE_Result (*set_alarm_wakeup_status)(struct rtc *rtc, bool status);
117 };
118 
119 #ifdef CFG_DRIVERS_RTC
120 extern struct rtc *rtc_device;
121 
122 /* Register a RTC device as the system RTC */
123 void rtc_register(struct rtc *rtc);
124 
125 /**
126  * rtc_is_a_leap_year() - Check if a year is a leap year
127  * @year:	The year to check
128  *
129  * Return:	true if the year is a leap year, false otherwise
130  */
131 bool rtc_is_a_leap_year(uint32_t year);
132 
133 /**
134  * rtc_get_month_days() - Get the number of days in a month
135  * @month:	The month to know the number of days
136  * @year:	The year of the month
137  *
138  * Return:	Number of days in the month
139  */
140 uint8_t rtc_get_month_days(uint32_t month, uint32_t year);
141 
142 /**
143  * rtc_timecmp() - Compare two RTC time structures
144  * @a:		First RTC time
145  * @b:		Second RTC time
146  *
147  * Return a negative value if @a < @b
148  * Return 0 if @a == @b
149  * Return a positive value if @a > @b
150  */
151 int rtc_timecmp(struct optee_rtc_time *a, struct optee_rtc_time *b);
152 
153 /**
154  * rtc_diff_calendar_ms() - Return the difference in milliseconds between
155  * two times captures.
156  * @ref1: First time capture
157  * @ref2: Second time capture
158  *
159  * Return @ref1 - @ref2 in milliseconds or LLONG_MAX in case of overflow
160  */
161 signed long long rtc_diff_calendar_ms(struct optee_rtc_time *ref1,
162 				      struct optee_rtc_time *ref2);
163 
164 /**
165  * rtc_diff_calendar_tick() - Return the difference in number of ticks between
166  * two times captures.
167  * @ref1: First time capture
168  * @ref2: Second time capture
169  * @tick_rate: Tick rate
170  *
171  * Return @ref1 - @ref2 in number of ticks. In case of tick computation
172  * overflow, return LLONG_MAX
173  */
174 signed long long rtc_diff_calendar_tick(struct optee_rtc_time *ref1,
175 					struct optee_rtc_time *ref2,
176 					unsigned long long tick_rate);
177 
rtc_get_info(uint64_t * features,struct optee_rtc_time * range_min,struct optee_rtc_time * range_max)178 static inline TEE_Result rtc_get_info(uint64_t *features,
179 				      struct optee_rtc_time *range_min,
180 				      struct optee_rtc_time *range_max)
181 {
182 	if (!rtc_device)
183 		return TEE_ERROR_NOT_SUPPORTED;
184 
185 	if (rtc_device->ops->set_offset)
186 		*features = RTC_CORRECTION_FEATURE;
187 	*range_min = rtc_device->range_min;
188 	*range_max = rtc_device->range_max;
189 
190 	if (rtc_device->ops->set_alarm)
191 		*features |= RTC_ALARM_FEATURE;
192 
193 	if (rtc_device->is_wakeup_source)
194 		*features |= RTC_WAKEUP_ALARM;
195 
196 	return TEE_SUCCESS;
197 }
198 
rtc_get_time(struct optee_rtc_time * tm)199 static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm)
200 {
201 	if (!rtc_device)
202 		return TEE_ERROR_NOT_SUPPORTED;
203 
204 	return rtc_device->ops->get_time(rtc_device, tm);
205 }
206 
rtc_set_time(struct optee_rtc_time * tm)207 static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm)
208 {
209 	if (!rtc_device || !rtc_device->ops->set_time)
210 		return TEE_ERROR_NOT_SUPPORTED;
211 
212 	if (tm->tm_mon >= 12 ||
213 	    tm->tm_mday > rtc_get_month_days(tm->tm_mon, tm->tm_year) ||
214 	    tm->tm_wday >= 7 || tm->tm_hour >= 24 || tm->tm_min >= 60 ||
215 	    tm->tm_sec >= 60 || tm->tm_ms >= 1000 ||
216 	    rtc_timecmp(tm, &rtc_device->range_min) < 0 ||
217 	    rtc_timecmp(tm, &rtc_device->range_max) > 0)
218 		return TEE_ERROR_BAD_PARAMETERS;
219 
220 	return rtc_device->ops->set_time(rtc_device, tm);
221 }
222 
rtc_get_offset(long * offset)223 static inline TEE_Result rtc_get_offset(long *offset)
224 {
225 	if (!rtc_device || !rtc_device->ops->get_offset)
226 		return TEE_ERROR_NOT_SUPPORTED;
227 
228 	return rtc_device->ops->get_offset(rtc_device, offset);
229 }
230 
rtc_set_offset(long offset)231 static inline TEE_Result rtc_set_offset(long offset)
232 {
233 	if (!rtc_device || !rtc_device->ops->set_offset)
234 		return TEE_ERROR_NOT_SUPPORTED;
235 
236 	return rtc_device->ops->set_offset(rtc_device, offset);
237 }
238 
rtc_read_alarm(struct optee_rtc_alarm * alarm)239 static inline TEE_Result rtc_read_alarm(struct optee_rtc_alarm *alarm)
240 {
241 	if (!rtc_device || !rtc_device->ops->read_alarm)
242 		return TEE_ERROR_NOT_SUPPORTED;
243 
244 	return rtc_device->ops->read_alarm(rtc_device, alarm);
245 }
246 
rtc_set_alarm(struct optee_rtc_alarm * alarm)247 static inline TEE_Result rtc_set_alarm(struct optee_rtc_alarm *alarm)
248 {
249 	if (!rtc_device || !rtc_device->ops->set_alarm)
250 		return TEE_ERROR_NOT_SUPPORTED;
251 
252 	return rtc_device->ops->set_alarm(rtc_device, alarm);
253 }
254 
rtc_enable_alarm(bool enable)255 static inline TEE_Result rtc_enable_alarm(bool enable)
256 {
257 	if (!rtc_device || !rtc_device->ops->enable_alarm)
258 		return TEE_ERROR_NOT_SUPPORTED;
259 
260 	return rtc_device->ops->enable_alarm(rtc_device, enable);
261 }
262 
rtc_wait_alarm(enum rtc_wait_alarm_status * status)263 static inline TEE_Result rtc_wait_alarm(enum rtc_wait_alarm_status *status)
264 {
265 	if (!rtc_device || !rtc_device->ops->wait_alarm)
266 		return TEE_ERROR_NOT_SUPPORTED;
267 
268 	return rtc_device->ops->wait_alarm(rtc_device, status);
269 }
270 
rtc_cancel_wait_alarm(void)271 static inline TEE_Result rtc_cancel_wait_alarm(void)
272 {
273 	if (!rtc_device || !rtc_device->ops->cancel_wait)
274 		return TEE_ERROR_NOT_SUPPORTED;
275 
276 	return rtc_device->ops->cancel_wait(rtc_device);
277 }
278 
rtc_set_alarm_wakeup_status(bool status)279 static inline TEE_Result rtc_set_alarm_wakeup_status(bool status)
280 {
281 	if (!rtc_device || !rtc_device->ops->set_alarm_wakeup_status)
282 		return TEE_ERROR_NOT_SUPPORTED;
283 
284 	return rtc_device->ops->set_alarm_wakeup_status(rtc_device, status);
285 }
286 #else
287 
rtc_register(struct rtc * rtc __unused)288 static inline void rtc_register(struct rtc *rtc __unused) {}
289 
rtc_is_a_leap_year(uint32_t year __unused)290 static inline bool __noreturn rtc_is_a_leap_year(uint32_t year __unused)
291 {
292 	panic();
293 }
294 
rtc_get_month_days(uint32_t month __unused,uint32_t year __unused)295 static inline uint8_t __noreturn rtc_get_month_days(uint32_t month __unused,
296 						    uint32_t year __unused)
297 {
298 	panic();
299 }
300 
rtc_timecmp(struct optee_rtc_time * a __unused,struct optee_rtc_time * b __unused)301 static inline int __noreturn rtc_timecmp(struct optee_rtc_time *a __unused,
302 					 struct optee_rtc_time *b __unused)
303 {
304 	panic();
305 }
306 
rtc_get_info(uint64_t * features __unused,struct optee_rtc_time * range_min __unused,struct optee_rtc_time * range_max __unused)307 static inline TEE_Result rtc_get_info(uint64_t *features __unused,
308 				      struct optee_rtc_time *range_min __unused,
309 				      struct optee_rtc_time *range_max __unused)
310 {
311 	return TEE_ERROR_NOT_SUPPORTED;
312 }
313 
rtc_get_time(struct optee_rtc_time * tm __unused)314 static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm __unused)
315 {
316 	return TEE_ERROR_NOT_SUPPORTED;
317 }
318 
rtc_set_time(struct optee_rtc_time * tm __unused)319 static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm __unused)
320 {
321 	return TEE_ERROR_NOT_SUPPORTED;
322 }
323 
rtc_get_offset(long * offset __unused)324 static inline TEE_Result rtc_get_offset(long *offset __unused)
325 {
326 	return TEE_ERROR_NOT_SUPPORTED;
327 }
328 
rtc_set_offset(long offset __unused)329 static inline TEE_Result rtc_set_offset(long offset __unused)
330 {
331 	return TEE_ERROR_NOT_SUPPORTED;
332 }
333 
334 static inline signed long long
rtc_diff_calendar_ms(struct optee_rtc_time * ref1 __unused,struct optee_rtc_time * ref2 __unused)335 rtc_diff_calendar_ms(struct optee_rtc_time *ref1 __unused,
336 		     struct optee_rtc_time *ref2 __unused)
337 {
338 	return LLONG_MAX;
339 }
340 
341 static inline signed long long
rtc_diff_calendar_tick(struct optee_rtc_time * ref1 __unused,struct optee_rtc_time * ref2 __unused,unsigned long long tick_rate __unused)342 rtc_diff_calendar_tick(struct optee_rtc_time *ref1 __unused,
343 		       struct optee_rtc_time *ref2 __unused,
344 		       unsigned long long tick_rate __unused)
345 {
346 	return LLONG_MAX;
347 }
348 
rtc_read_alarm(struct optee_rtc_alarm * alarm __unused)349 static inline TEE_Result rtc_read_alarm(struct optee_rtc_alarm *alarm __unused)
350 {
351 	return TEE_ERROR_NOT_SUPPORTED;
352 }
353 
rtc_set_alarm(struct optee_rtc_alarm * alarm __unused)354 static inline TEE_Result rtc_set_alarm(struct optee_rtc_alarm *alarm __unused)
355 {
356 	return TEE_ERROR_NOT_SUPPORTED;
357 }
358 
rtc_enable_alarm(bool enable __unused)359 static inline TEE_Result rtc_enable_alarm(bool enable __unused)
360 {
361 	return TEE_ERROR_NOT_SUPPORTED;
362 }
363 
364 static inline TEE_Result
rtc_wait_alarm(enum rtc_wait_alarm_status * status __unused)365 rtc_wait_alarm(enum rtc_wait_alarm_status *status __unused)
366 {
367 	return TEE_ERROR_NOT_SUPPORTED;
368 }
369 
rtc_cancel_wait_alarm(void)370 static inline TEE_Result rtc_cancel_wait_alarm(void)
371 {
372 	return TEE_ERROR_NOT_SUPPORTED;
373 }
374 
rtc_set_alarm_wakeup_status(bool status __unused)375 static inline TEE_Result rtc_set_alarm_wakeup_status(bool status __unused)
376 {
377 	return TEE_ERROR_NOT_SUPPORTED;
378 }
379 #endif
380 #endif /* __DRIVERS_RTC_H */
381