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 926899ca2SClé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 1626899ca2SClément Le Goffic #define MS_PER_SEC 1000 1726899ca2SClément Le Goffic #define MS_PER_MIN (60 * MS_PER_SEC) 1826899ca2SClément Le Goffic #define MS_PER_HOUR (60 * MS_PER_MIN) 1926899ca2SClément Le Goffic #define MS_PER_DAY (24 * MS_PER_HOUR) 2026899ca2SClément Le Goffic 21*a83e616eSGatien Chevallier #define RTC_TIME(year, mon, mday, wday, hour, min, sec, ms) \ 22*a83e616eSGatien Chevallier { \ 23*a83e616eSGatien Chevallier .tm_year = (year), \ 24*a83e616eSGatien Chevallier .tm_mon = (mon), \ 25*a83e616eSGatien Chevallier .tm_mday = (mday), \ 26*a83e616eSGatien Chevallier .tm_wday = (wday), \ 27*a83e616eSGatien Chevallier .tm_hour = (hour), \ 28*a83e616eSGatien Chevallier .tm_min = (min), \ 29*a83e616eSGatien Chevallier .tm_sec = (sec), \ 30*a83e616eSGatien Chevallier .tm_ms = (ms), \ 31*a83e616eSGatien Chevallier } 32*a83e616eSGatien Chevallier 3326899ca2SClément Le Goffic /* 3426899ca2SClément Le Goffic * struct optee_rtc_time - Time in Gregorian calendar 3526899ca2SClément Le Goffic * 3626899ca2SClément Le Goffic * @tm_year: Absolute year 3726899ca2SClément Le Goffic * @tm_mon: Month: 0=January, 1=February, ..., 11=December 3826899ca2SClément Le Goffic * @tm_mday: Month day start from 1 3926899ca2SClément Le Goffic * @tm_wday: Week day: 0=Sunday, 1=Monday, ..., 6=Saturday 4026899ca2SClément Le Goffic * @tm_hour: Hour in range [0 23] 4126899ca2SClément Le Goffic * @tm_min: Minute in range [0 59] 4226899ca2SClément Le Goffic * @tm_sec: Second in range [0 59] 4326899ca2SClément Le Goffic * @tm_ms: Millisecond in range [0 999] or 0 if no applicable 4426899ca2SClément Le Goffic */ 45f3f9432fSClément Léger struct optee_rtc_time { 46f3f9432fSClément Léger uint32_t tm_year; 47f3f9432fSClément Léger uint32_t tm_mon; 48f3f9432fSClément Léger uint32_t tm_mday; 4926899ca2SClément Le Goffic uint32_t tm_wday; 50f3f9432fSClément Léger uint32_t tm_hour; 51f3f9432fSClément Léger uint32_t tm_min; 52f3f9432fSClément Léger uint32_t tm_sec; 5326899ca2SClément Le Goffic uint32_t tm_ms; 54f3f9432fSClément Léger }; 55f3f9432fSClément Léger 56f3f9432fSClément Léger struct rtc { 57f3f9432fSClément Léger const struct rtc_ops *ops; 58f3f9432fSClément Léger struct optee_rtc_time range_min; 59f3f9432fSClément Léger struct optee_rtc_time range_max; 60f3f9432fSClément Léger }; 61f3f9432fSClément Léger 62f3f9432fSClément Léger /* 63f3f9432fSClément Léger * struct rtc_ops - The RTC device operations 64f3f9432fSClément Léger * 65f3f9432fSClément Léger * @get_time: Get the RTC time. 66f3f9432fSClément Léger * @set_time: Set the RTC time. 67f3f9432fSClément Léger * @get_offset: Get the RTC offset. 68f3f9432fSClément Léger * @set_offset: Set the RTC offset 69f3f9432fSClément Léger */ 70f3f9432fSClément Léger struct rtc_ops { 71f3f9432fSClément Léger TEE_Result (*get_time)(struct rtc *rtc, struct optee_rtc_time *tm); 72f3f9432fSClément Léger TEE_Result (*set_time)(struct rtc *rtc, struct optee_rtc_time *tm); 73f3f9432fSClément Léger TEE_Result (*get_offset)(struct rtc *rtc, long *offset); 74f3f9432fSClément Léger TEE_Result (*set_offset)(struct rtc *rtc, long offset); 75f3f9432fSClément Léger }; 76f3f9432fSClément Léger 77f3f9432fSClément Léger #ifdef CFG_DRIVERS_RTC 78f3f9432fSClément Léger extern struct rtc *rtc_device; 79f3f9432fSClément Léger 80f3f9432fSClément Léger /* Register a RTC device as the system RTC */ 81f3f9432fSClément Léger void rtc_register(struct rtc *rtc); 82f3f9432fSClément Léger 8326899ca2SClément Le Goffic /** 8426899ca2SClément Le Goffic * rtc_is_a_leap_year() - Check if a year is a leap year 8526899ca2SClément Le Goffic * @year: The year to check 8626899ca2SClément Le Goffic * 8726899ca2SClément Le Goffic * Return: true if the year is a leap year, false otherwise 8826899ca2SClément Le Goffic */ 8926899ca2SClément Le Goffic bool rtc_is_a_leap_year(uint32_t year); 9026899ca2SClément Le Goffic 9126899ca2SClément Le Goffic /** 9226899ca2SClément Le Goffic * rtc_get_month_days() - Get the number of days in a month 9326899ca2SClément Le Goffic * @month: The month to know the number of days 9426899ca2SClément Le Goffic * @year: The year of the month 9526899ca2SClément Le Goffic * 9626899ca2SClément Le Goffic * Return: Number of days in the month 9726899ca2SClément Le Goffic */ 9826899ca2SClément Le Goffic uint8_t rtc_get_month_days(uint32_t month, uint32_t year); 9926899ca2SClément Le Goffic 10026899ca2SClément Le Goffic /** 10126899ca2SClément Le Goffic * rtc_timecmp() - Compare two RTC time structures 10226899ca2SClément Le Goffic * @a: First RTC time 10326899ca2SClément Le Goffic * @b: Second RTC time 10426899ca2SClément Le Goffic * 10526899ca2SClément Le Goffic * Return a negative value if @a < @b 10626899ca2SClément Le Goffic * Return 0 if @a == @b 10726899ca2SClément Le Goffic * Return a positive value if @a > @b 10826899ca2SClément Le Goffic */ 10926899ca2SClément Le Goffic int rtc_timecmp(struct optee_rtc_time *a, struct optee_rtc_time *b); 11026899ca2SClément Le Goffic 11126899ca2SClément Le Goffic /** 11226899ca2SClément Le Goffic * rtc_diff_calendar_ms() - Return the difference in milliseconds between 11326899ca2SClément Le Goffic * two times captures. 11426899ca2SClément Le Goffic * @ref1: First time capture 11526899ca2SClément Le Goffic * @ref2: Second time capture 11626899ca2SClément Le Goffic * 11726899ca2SClément Le Goffic * Return @ref1 - @ref2 in milliseconds or LLONG_MAX in case of overflow 11826899ca2SClément Le Goffic */ 11926899ca2SClément Le Goffic signed long long rtc_diff_calendar_ms(struct optee_rtc_time *ref1, 12026899ca2SClément Le Goffic struct optee_rtc_time *ref2); 12126899ca2SClément Le Goffic 12226899ca2SClément Le Goffic /** 12326899ca2SClément Le Goffic * rtc_diff_calendar_tick() - Return the difference in number of ticks between 12426899ca2SClément Le Goffic * two times captures. 12526899ca2SClément Le Goffic * @ref1: First time capture 12626899ca2SClément Le Goffic * @ref2: Second time capture 12726899ca2SClément Le Goffic * @tick_rate: Tick rate 12826899ca2SClément Le Goffic * 12926899ca2SClément Le Goffic * Return @ref1 - @ref2 in number of ticks. In case of tick computation 13026899ca2SClément Le Goffic * overflow, return LLONG_MAX 13126899ca2SClément Le Goffic */ 13226899ca2SClément Le Goffic signed long long rtc_diff_calendar_tick(struct optee_rtc_time *ref1, 13326899ca2SClément Le Goffic struct optee_rtc_time *ref2, 13426899ca2SClément Le Goffic unsigned long long tick_rate); 13526899ca2SClément Le Goffic 136f3f9432fSClément Léger static inline TEE_Result rtc_get_info(uint64_t *features, 137f3f9432fSClément Léger struct optee_rtc_time *range_min, 138f3f9432fSClément Léger struct optee_rtc_time *range_max) 139f3f9432fSClément Léger { 140f3f9432fSClément Léger if (!rtc_device) 141f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 142f3f9432fSClément Léger 143f3f9432fSClément Léger if (rtc_device->ops->set_offset) 144f3f9432fSClément Léger *features = RTC_CORRECTION_FEATURE; 145f3f9432fSClément Léger *range_min = rtc_device->range_min; 146f3f9432fSClément Léger *range_max = rtc_device->range_max; 147f3f9432fSClément Léger 148f3f9432fSClément Léger return TEE_SUCCESS; 149f3f9432fSClément Léger } 150f3f9432fSClément Léger 151f3f9432fSClément Léger static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm) 152f3f9432fSClément Léger { 153f3f9432fSClément Léger if (!rtc_device) 154f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 155f3f9432fSClément Léger 156f3f9432fSClément Léger return rtc_device->ops->get_time(rtc_device, tm); 157f3f9432fSClément Léger } 158f3f9432fSClément Léger 159f3f9432fSClément Léger static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm) 160f3f9432fSClément Léger { 161f3f9432fSClément Léger if (!rtc_device || !rtc_device->ops->set_time) 162f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 163f3f9432fSClément Léger 164f3f9432fSClément Léger return rtc_device->ops->set_time(rtc_device, tm); 165f3f9432fSClément Léger } 166f3f9432fSClément Léger 167f3f9432fSClément Léger static inline TEE_Result rtc_get_offset(long *offset) 168f3f9432fSClément Léger { 169f3f9432fSClément Léger if (!rtc_device || !rtc_device->ops->get_offset) 170f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 171f3f9432fSClément Léger 172f3f9432fSClément Léger return rtc_device->ops->get_offset(rtc_device, offset); 173f3f9432fSClément Léger } 174f3f9432fSClément Léger 175f3f9432fSClément Léger static inline TEE_Result rtc_set_offset(long offset) 176f3f9432fSClément Léger { 177f3f9432fSClément Léger if (!rtc_device || !rtc_device->ops->set_offset) 178f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 179f3f9432fSClément Léger 180f3f9432fSClément Léger return rtc_device->ops->set_offset(rtc_device, offset); 181f3f9432fSClément Léger } 182f3f9432fSClément Léger 183f3f9432fSClément Léger #else 184f3f9432fSClément Léger 185f3f9432fSClément Léger static inline void rtc_register(struct rtc *rtc __unused) {} 186f3f9432fSClément Léger 18726899ca2SClément Le Goffic static inline bool __noreturn rtc_is_a_leap_year(uint32_t year __unused) 18826899ca2SClément Le Goffic { 18926899ca2SClément Le Goffic panic(); 19026899ca2SClément Le Goffic } 19126899ca2SClément Le Goffic 19226899ca2SClément Le Goffic static inline uint8_t __noreturn rtc_get_month_days(uint32_t month __unused, 19326899ca2SClément Le Goffic uint32_t year __unused) 19426899ca2SClément Le Goffic { 19526899ca2SClément Le Goffic panic(); 19626899ca2SClément Le Goffic } 19726899ca2SClément Le Goffic 19826899ca2SClément Le Goffic static inline int __noreturn rtc_timecmp(struct optee_rtc_time *a __unused, 19926899ca2SClément Le Goffic struct optee_rtc_time *b __unused) 20026899ca2SClément Le Goffic { 20126899ca2SClément Le Goffic panic(); 20226899ca2SClément Le Goffic } 20326899ca2SClément Le Goffic 204f3f9432fSClément Léger static inline TEE_Result rtc_get_info(uint64_t *features __unused, 205f3f9432fSClément Léger struct optee_rtc_time *range_min __unused, 206f3f9432fSClément Léger struct optee_rtc_time *range_max __unused) 207f3f9432fSClément Léger { 208f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 209f3f9432fSClément Léger } 210f3f9432fSClément Léger 211f3f9432fSClément Léger static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm __unused) 212f3f9432fSClément Léger { 213f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 214f3f9432fSClément Léger } 215f3f9432fSClément Léger 216f3f9432fSClément Léger static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm __unused) 217f3f9432fSClément Léger { 218f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 219f3f9432fSClément Léger } 220f3f9432fSClément Léger 221f3f9432fSClément Léger static inline TEE_Result rtc_get_offset(long *offset __unused) 222f3f9432fSClément Léger { 223f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 224f3f9432fSClément Léger } 225f3f9432fSClément Léger 226f3f9432fSClément Léger static inline TEE_Result rtc_set_offset(long offset __unused) 227f3f9432fSClément Léger { 228f3f9432fSClément Léger return TEE_ERROR_NOT_SUPPORTED; 229f3f9432fSClément Léger } 23026899ca2SClément Le Goffic 23126899ca2SClément Le Goffic static inline signed long long 23226899ca2SClément Le Goffic rtc_diff_calendar_ms(struct optee_rtc_time *ref1 __unused, 23326899ca2SClément Le Goffic struct optee_rtc_time *ref2 __unused) 23426899ca2SClément Le Goffic { 23526899ca2SClément Le Goffic return LLONG_MAX; 23626899ca2SClément Le Goffic } 23726899ca2SClément Le Goffic 23826899ca2SClément Le Goffic static inline signed long long 23926899ca2SClément Le Goffic rtc_diff_calendar_tick(struct optee_rtc_time *ref1 __unused, 24026899ca2SClément Le Goffic struct optee_rtc_time *ref2 __unused, 24126899ca2SClément Le Goffic unsigned long long tick_rate __unused) 24226899ca2SClément Le Goffic { 24326899ca2SClément Le Goffic return LLONG_MAX; 24426899ca2SClément Le Goffic } 245f3f9432fSClément Léger #endif 246d50fee03SEtienne Carriere #endif /* __DRIVERS_RTC_H */ 247