xref: /optee_os/core/include/drivers/rtc.h (revision 26899ca2e2f4cbe2b26643c60891f8596c715233)
1f3f9432fSClément Léger /* SPDX-License-Identifier: BSD-2-Clause */
2f3f9432fSClément Léger /*
3f3f9432fSClément Léger  * Copyright 2022 Microchip.
4f3f9432fSClément Léger  */
5f3f9432fSClément Léger 
6d50fee03SEtienne Carriere #ifndef __DRIVERS_RTC_H
7d50fee03SEtienne Carriere #define __DRIVERS_RTC_H
8f3f9432fSClément Léger 
9*26899ca2SClément Le Goffic #include <kernel/panic.h>
10f3f9432fSClément Léger #include <tee_api_types.h>
11f3f9432fSClément Léger #include <util.h>
12f3f9432fSClément Léger 
13f3f9432fSClément Léger /* The RTC allows to set/get offset for correction */
14f3f9432fSClément Léger #define RTC_CORRECTION_FEATURE	BIT(0)
15f3f9432fSClément Léger 
16*26899ca2SClément Le Goffic #define MS_PER_SEC		1000
17*26899ca2SClément Le Goffic #define MS_PER_MIN		(60 * MS_PER_SEC)
18*26899ca2SClément Le Goffic #define MS_PER_HOUR		(60 * MS_PER_MIN)
19*26899ca2SClément Le Goffic #define MS_PER_DAY		(24 * MS_PER_HOUR)
20*26899ca2SClément Le Goffic 
21*26899ca2SClément Le Goffic /*
22*26899ca2SClément Le Goffic  * struct optee_rtc_time - Time in Gregorian calendar
23*26899ca2SClément Le Goffic  *
24*26899ca2SClément Le Goffic  * @tm_year: Absolute year
25*26899ca2SClément Le Goffic  * @tm_mon: Month: 0=January, 1=February, ..., 11=December
26*26899ca2SClément Le Goffic  * @tm_mday: Month day start from 1
27*26899ca2SClément Le Goffic  * @tm_wday: Week day: 0=Sunday, 1=Monday, ..., 6=Saturday
28*26899ca2SClément Le Goffic  * @tm_hour: Hour in range [0 23]
29*26899ca2SClément Le Goffic  * @tm_min: Minute in range [0 59]
30*26899ca2SClément Le Goffic  * @tm_sec: Second in range [0 59]
31*26899ca2SClément Le Goffic  * @tm_ms: Millisecond in range [0 999] or 0 if no applicable
32*26899ca2SClément Le Goffic  */
33f3f9432fSClément Léger struct optee_rtc_time {
34f3f9432fSClément Léger 	uint32_t tm_year;
35f3f9432fSClément Léger 	uint32_t tm_mon;
36f3f9432fSClément Léger 	uint32_t tm_mday;
37*26899ca2SClément Le Goffic 	uint32_t tm_wday;
38f3f9432fSClément Léger 	uint32_t tm_hour;
39f3f9432fSClément Léger 	uint32_t tm_min;
40f3f9432fSClément Léger 	uint32_t tm_sec;
41*26899ca2SClément Le Goffic 	uint32_t tm_ms;
42f3f9432fSClément Léger };
43f3f9432fSClément Léger 
44f3f9432fSClément Léger struct rtc {
45f3f9432fSClément Léger 	const struct rtc_ops *ops;
46f3f9432fSClément Léger 	struct optee_rtc_time range_min;
47f3f9432fSClément Léger 	struct optee_rtc_time range_max;
48f3f9432fSClément Léger };
49f3f9432fSClément Léger 
50f3f9432fSClément Léger /*
51f3f9432fSClément Léger  * struct rtc_ops - The RTC device operations
52f3f9432fSClément Léger  *
53f3f9432fSClément Léger  * @get_time:	Get the RTC time.
54f3f9432fSClément Léger  * @set_time:	Set the RTC time.
55f3f9432fSClément Léger  * @get_offset:	Get the RTC offset.
56f3f9432fSClément Léger  * @set_offset: Set the RTC offset
57f3f9432fSClément Léger  */
58f3f9432fSClément Léger struct rtc_ops {
59f3f9432fSClément Léger 	TEE_Result (*get_time)(struct rtc *rtc, struct optee_rtc_time *tm);
60f3f9432fSClément Léger 	TEE_Result (*set_time)(struct rtc *rtc, struct optee_rtc_time *tm);
61f3f9432fSClément Léger 	TEE_Result (*get_offset)(struct rtc *rtc, long *offset);
62f3f9432fSClément Léger 	TEE_Result (*set_offset)(struct rtc *rtc, long offset);
63f3f9432fSClément Léger };
64f3f9432fSClément Léger 
65f3f9432fSClément Léger #ifdef CFG_DRIVERS_RTC
66f3f9432fSClément Léger extern struct rtc *rtc_device;
67f3f9432fSClément Léger 
68f3f9432fSClément Léger /* Register a RTC device as the system RTC */
69f3f9432fSClément Léger void rtc_register(struct rtc *rtc);
70f3f9432fSClément Léger 
71*26899ca2SClément Le Goffic /**
72*26899ca2SClément Le Goffic  * rtc_is_a_leap_year() - Check if a year is a leap year
73*26899ca2SClément Le Goffic  * @year:	The year to check
74*26899ca2SClément Le Goffic  *
75*26899ca2SClément Le Goffic  * Return:	true if the year is a leap year, false otherwise
76*26899ca2SClément Le Goffic  */
77*26899ca2SClément Le Goffic bool rtc_is_a_leap_year(uint32_t year);
78*26899ca2SClément Le Goffic 
79*26899ca2SClément Le Goffic /**
80*26899ca2SClément Le Goffic  * rtc_get_month_days() - Get the number of days in a month
81*26899ca2SClément Le Goffic  * @month:	The month to know the number of days
82*26899ca2SClément Le Goffic  * @year:	The year of the month
83*26899ca2SClément Le Goffic  *
84*26899ca2SClément Le Goffic  * Return:	Number of days in the month
85*26899ca2SClément Le Goffic  */
86*26899ca2SClément Le Goffic uint8_t rtc_get_month_days(uint32_t month, uint32_t year);
87*26899ca2SClément Le Goffic 
88*26899ca2SClément Le Goffic /**
89*26899ca2SClément Le Goffic  * rtc_timecmp() - Compare two RTC time structures
90*26899ca2SClément Le Goffic  * @a:		First RTC time
91*26899ca2SClément Le Goffic  * @b:		Second RTC time
92*26899ca2SClément Le Goffic  *
93*26899ca2SClément Le Goffic  * Return a negative value if @a < @b
94*26899ca2SClément Le Goffic  * Return 0 if @a == @b
95*26899ca2SClément Le Goffic  * Return a positive value if @a > @b
96*26899ca2SClément Le Goffic  */
97*26899ca2SClément Le Goffic int rtc_timecmp(struct optee_rtc_time *a, struct optee_rtc_time *b);
98*26899ca2SClément Le Goffic 
99*26899ca2SClément Le Goffic /**
100*26899ca2SClément Le Goffic  * rtc_diff_calendar_ms() - Return the difference in milliseconds between
101*26899ca2SClément Le Goffic  * two times captures.
102*26899ca2SClément Le Goffic  * @ref1: First time capture
103*26899ca2SClément Le Goffic  * @ref2: Second time capture
104*26899ca2SClément Le Goffic  *
105*26899ca2SClément Le Goffic  * Return @ref1 - @ref2 in milliseconds or LLONG_MAX in case of overflow
106*26899ca2SClément Le Goffic  */
107*26899ca2SClément Le Goffic signed long long rtc_diff_calendar_ms(struct optee_rtc_time *ref1,
108*26899ca2SClément Le Goffic 				      struct optee_rtc_time *ref2);
109*26899ca2SClément Le Goffic 
110*26899ca2SClément Le Goffic /**
111*26899ca2SClément Le Goffic  * rtc_diff_calendar_tick() - Return the difference in number of ticks between
112*26899ca2SClément Le Goffic  * two times captures.
113*26899ca2SClément Le Goffic  * @ref1: First time capture
114*26899ca2SClément Le Goffic  * @ref2: Second time capture
115*26899ca2SClément Le Goffic  * @tick_rate: Tick rate
116*26899ca2SClément Le Goffic  *
117*26899ca2SClément Le Goffic  * Return @ref1 - @ref2 in number of ticks. In case of tick computation
118*26899ca2SClément Le Goffic  * overflow, return LLONG_MAX
119*26899ca2SClément Le Goffic  */
120*26899ca2SClément Le Goffic signed long long rtc_diff_calendar_tick(struct optee_rtc_time *ref1,
121*26899ca2SClément Le Goffic 					struct optee_rtc_time *ref2,
122*26899ca2SClément Le Goffic 					unsigned long long tick_rate);
123*26899ca2SClément Le Goffic 
124f3f9432fSClément Léger static inline TEE_Result rtc_get_info(uint64_t *features,
125f3f9432fSClément Léger 				      struct optee_rtc_time *range_min,
126f3f9432fSClément Léger 				      struct optee_rtc_time *range_max)
127f3f9432fSClément Léger {
128f3f9432fSClément Léger 	if (!rtc_device)
129f3f9432fSClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
130f3f9432fSClément Léger 
131f3f9432fSClément Léger 	if (rtc_device->ops->set_offset)
132f3f9432fSClément Léger 		*features = RTC_CORRECTION_FEATURE;
133f3f9432fSClément Léger 	*range_min = rtc_device->range_min;
134f3f9432fSClément Léger 	*range_max = rtc_device->range_max;
135f3f9432fSClément Léger 
136f3f9432fSClément Léger 	return TEE_SUCCESS;
137f3f9432fSClément Léger }
138f3f9432fSClément Léger 
139f3f9432fSClément Léger static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm)
140f3f9432fSClément Léger {
141f3f9432fSClément Léger 	if (!rtc_device)
142f3f9432fSClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
143f3f9432fSClément Léger 
144f3f9432fSClément Léger 	return rtc_device->ops->get_time(rtc_device, tm);
145f3f9432fSClément Léger }
146f3f9432fSClément Léger 
147f3f9432fSClément Léger static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm)
148f3f9432fSClément Léger {
149f3f9432fSClément Léger 	if (!rtc_device || !rtc_device->ops->set_time)
150f3f9432fSClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
151f3f9432fSClément Léger 
152f3f9432fSClément Léger 	return rtc_device->ops->set_time(rtc_device, tm);
153f3f9432fSClément Léger }
154f3f9432fSClément Léger 
155f3f9432fSClément Léger static inline TEE_Result rtc_get_offset(long *offset)
156f3f9432fSClément Léger {
157f3f9432fSClément Léger 	if (!rtc_device || !rtc_device->ops->get_offset)
158f3f9432fSClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
159f3f9432fSClément Léger 
160f3f9432fSClément Léger 	return rtc_device->ops->get_offset(rtc_device, offset);
161f3f9432fSClément Léger }
162f3f9432fSClément Léger 
163f3f9432fSClément Léger static inline TEE_Result rtc_set_offset(long offset)
164f3f9432fSClément Léger {
165f3f9432fSClément Léger 	if (!rtc_device || !rtc_device->ops->set_offset)
166f3f9432fSClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
167f3f9432fSClément Léger 
168f3f9432fSClément Léger 	return rtc_device->ops->set_offset(rtc_device, offset);
169f3f9432fSClément Léger }
170f3f9432fSClément Léger 
171f3f9432fSClément Léger #else
172f3f9432fSClément Léger 
173f3f9432fSClément Léger static inline void rtc_register(struct rtc *rtc __unused) {}
174f3f9432fSClément Léger 
175*26899ca2SClément Le Goffic static inline bool __noreturn rtc_is_a_leap_year(uint32_t year __unused)
176*26899ca2SClément Le Goffic {
177*26899ca2SClément Le Goffic 	panic();
178*26899ca2SClément Le Goffic }
179*26899ca2SClément Le Goffic 
180*26899ca2SClément Le Goffic static inline uint8_t __noreturn rtc_get_month_days(uint32_t month __unused,
181*26899ca2SClément Le Goffic 						    uint32_t year __unused)
182*26899ca2SClément Le Goffic {
183*26899ca2SClément Le Goffic 	panic();
184*26899ca2SClément Le Goffic }
185*26899ca2SClément Le Goffic 
186*26899ca2SClément Le Goffic static inline int __noreturn rtc_timecmp(struct optee_rtc_time *a __unused,
187*26899ca2SClément Le Goffic 					 struct optee_rtc_time *b __unused)
188*26899ca2SClément Le Goffic {
189*26899ca2SClément Le Goffic 	panic();
190*26899ca2SClément Le Goffic }
191*26899ca2SClément Le Goffic 
192f3f9432fSClément Léger static inline TEE_Result rtc_get_info(uint64_t *features __unused,
193f3f9432fSClément Léger 				      struct optee_rtc_time *range_min __unused,
194f3f9432fSClément Léger 				      struct optee_rtc_time *range_max __unused)
195f3f9432fSClément Léger {
196f3f9432fSClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
197f3f9432fSClément Léger }
198f3f9432fSClément Léger 
199f3f9432fSClément Léger static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm __unused)
200f3f9432fSClément Léger {
201f3f9432fSClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
202f3f9432fSClément Léger }
203f3f9432fSClément Léger 
204f3f9432fSClément Léger static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm __unused)
205f3f9432fSClément Léger {
206f3f9432fSClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
207f3f9432fSClément Léger }
208f3f9432fSClément Léger 
209f3f9432fSClément Léger static inline TEE_Result rtc_get_offset(long *offset __unused)
210f3f9432fSClément Léger {
211f3f9432fSClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
212f3f9432fSClément Léger }
213f3f9432fSClément Léger 
214f3f9432fSClément Léger static inline TEE_Result rtc_set_offset(long offset __unused)
215f3f9432fSClément Léger {
216f3f9432fSClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
217f3f9432fSClément Léger }
218*26899ca2SClément Le Goffic 
219*26899ca2SClément Le Goffic static inline signed long long
220*26899ca2SClément Le Goffic rtc_diff_calendar_ms(struct optee_rtc_time *ref1 __unused,
221*26899ca2SClément Le Goffic 		     struct optee_rtc_time *ref2 __unused)
222*26899ca2SClément Le Goffic {
223*26899ca2SClément Le Goffic 	return LLONG_MAX;
224*26899ca2SClément Le Goffic }
225*26899ca2SClément Le Goffic 
226*26899ca2SClément Le Goffic static inline signed long long
227*26899ca2SClément Le Goffic rtc_diff_calendar_tick(struct optee_rtc_time *ref1 __unused,
228*26899ca2SClément Le Goffic 		       struct optee_rtc_time *ref2 __unused,
229*26899ca2SClément Le Goffic 		       unsigned long long tick_rate __unused)
230*26899ca2SClément Le Goffic {
231*26899ca2SClément Le Goffic 	return LLONG_MAX;
232*26899ca2SClément Le Goffic }
233f3f9432fSClément Léger #endif
234d50fee03SEtienne Carriere #endif /* __DRIVERS_RTC_H */
235