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 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 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 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 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 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 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 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 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 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 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 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 288 static inline void rtc_register(struct rtc *rtc __unused) {} 289 290 static inline bool __noreturn rtc_is_a_leap_year(uint32_t year __unused) 291 { 292 panic(); 293 } 294 295 static inline uint8_t __noreturn rtc_get_month_days(uint32_t month __unused, 296 uint32_t year __unused) 297 { 298 panic(); 299 } 300 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 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 314 static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm __unused) 315 { 316 return TEE_ERROR_NOT_SUPPORTED; 317 } 318 319 static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm __unused) 320 { 321 return TEE_ERROR_NOT_SUPPORTED; 322 } 323 324 static inline TEE_Result rtc_get_offset(long *offset __unused) 325 { 326 return TEE_ERROR_NOT_SUPPORTED; 327 } 328 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 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 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 349 static inline TEE_Result rtc_read_alarm(struct optee_rtc_alarm *alarm __unused) 350 { 351 return TEE_ERROR_NOT_SUPPORTED; 352 } 353 354 static inline TEE_Result rtc_set_alarm(struct optee_rtc_alarm *alarm __unused) 355 { 356 return TEE_ERROR_NOT_SUPPORTED; 357 } 358 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 365 rtc_wait_alarm(enum rtc_wait_alarm_status *status __unused) 366 { 367 return TEE_ERROR_NOT_SUPPORTED; 368 } 369 370 static inline TEE_Result rtc_cancel_wait_alarm(void) 371 { 372 return TEE_ERROR_NOT_SUPPORTED; 373 } 374 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