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