/** * @file sdrv_rtc.h * @brief SemiDrive RTC driver header file. * * @copyright Copyright (c) 2022 Semidrive Semiconductor. * All rights reserved. */ #ifndef _SDRV_RTC_H_ #define _SDRV_RTC_H_ #include #include #include #include #include #define SDRV_RTC_REG_PARITY_ERR_ENABLE() \ sdrv_rtc_reg_parity_err_int_enable(APB_RTC1_BASE); \ sdrv_rtc_reg_parity_err_int_enable(APB_RTC2_BASE); #define SDRV_RTC_REG_PARITY_ERR_DISABLE() \ sdrv_rtc_reg_parity_err_int_disable(APB_RTC1_BASE); \ sdrv_rtc_reg_parity_err_int_disable(APB_RTC2_BASE); typedef int (*rtc_cb_t)(uint32_t irq, void *arg); /** * @brief RTC time structure. * * The RTC time structure uses Gregorian time. */ struct rtc_time { uint32_t tm_subsec;/* subseconds, unit millisecond, 0~999 */ uint32_t tm_sec; /* seconds, 0~61 */ uint32_t tm_min; /* minutes, 0~59 */ uint32_t tm_hour; /* hour, 0~23 */ uint32_t tm_mday; /* day, 1~31 */ uint32_t tm_mon; /* month, 0~11 */ uint32_t tm_year; /* years since 1900 */ uint32_t tm_wday; /* day since Sunday, 0~6 */ uint32_t tm_yday; /* days since Jan. 1, 0~365 */ uint32_t tm_isdst; /* daylight saving time flag */ }; typedef enum sdrv_rtc_violation_enum { SDRV_RTC_VIO_NONE = 0, /* rtc no violation */ SDRV_RTC_VIO_OVERFLOW = 1, /* rtc violation disable */ SDRV_RTC_VIO_DISABLE = 2, /* rtc violation overflow */ SDRV_RTC_VIO_ALL = 3, /* rtc violation overflow & disable */ } sdrv_rtc_violation_e; /** * @brief RTC device structure. */ typedef struct sdrv_rtc { paddr_t base; uint32_t wakeup_intr; /**< wake up interrupt num */ uint32_t periodic_intr; /**< periodical interrupt num */ uint32_t violation_intr; /**< violation interrupt num */ rtc_cb_t cb; /**< interrupt callback */ sdrv_rtc_violation_e vio_mask; /**< mask flag in violation interrupt */ } sdrv_rtc_t; struct rtc_wkalrm { unsigned char enable; unsigned char pending; struct rtc_time tm; }; /* Define RTC WakeUp Enable Type */ typedef enum sdrv_rtc_wakeup_enable_type { SDRV_WKUP_ENABLE = 0, /* Only enable wakeup */ SDRV_WKUP_ENABLE_IRQ = 1, /* Enable wakeup and IRQ */ SDRV_WKUP_ENABLE_REQ = 2, /* Enable wakeup and pmu requst */ SDRV_WKUP_ENABLE_ALL = 3, /* Enable wakeup, IRQ and pmu requst */ } sdrv_rtc_wakeup_enable_type_e; typedef enum sdrv_general_purpose { SDRV_RTC_GP0, /* RTC general purpose register 0 */ SDRV_RTC_GP1, /* RTC general purpose register 1 */ SDRV_RTC_GP2, /* RTC general purpose register 2 */ SDRV_RTC_GP3, /* RTC general purpose register 3 */ } sdrv_general_purpose_e; /** * @brief RTC status error code. */ enum sdrv_rtc_error { SDRV_RTC_STATUS_INVALID_RTC_TIME = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_RTC, 1), /* Invalid RTC Time */ SDRV_RTC_STATUS_LOCK = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_RTC, 2), /* RTC lock error */ }; /** * @brief Enable RTC Register parity error interrupt status. * * @param base RTC Controller Base. */ static inline void sdrv_rtc_reg_parity_err_int_enable(uint32_t base) { RMWREG32(base + 0x68U, 0, 1, 1); } /** * @brief Disable RTC Register parity error interrupt status. * * @param base RTC Controller Base. */ static inline void sdrv_rtc_reg_parity_err_int_disable(uint32_t base) { RMWREG32(base + 0x68U, 0, 1, 0); } /** * @brief check is leap yaer * * @param [in] year * @return true is leap year, false is not leap year. */ static inline bool is_leap_year(uint32_t year) { return (!(year % 4) && (year % 100)) || !(year % 400); } /** * @brief Simple algorithm to convert RTC time to Epoch seconds. * * Epoch seconds starts from 1970-1-1, 00:00:01 * * @param [in] tm rtc time. * @return uint64_t Number of seconds since Epoch. */ uint64_t rtc_to_epoch(struct rtc_time *tm); /** * @brief Simple algorithm to convert epoch seconds to RTC time. * * Epoch seconds starts from 1970-1-1, 00:00:01 * * @param [out] tm rtc time * @param [in] epoch_sec uint64_t number of seconds since epoch. * @return 0 success, otherwise failed. */ status_t epoch_to_rtc(struct rtc_time *tm, uint64_t epoch_sec); /** * @brief Simple algorithm to convert RTC time to Epoch milliseconds. * * Epoch seconds starts from 1970-1-1, 00:00:00.001 * * @param [in] tm rtc time. * @return uint64_t number of milliseconds since epoch. */ uint64_t rtc_to_epoch_ms(struct rtc_time *tm); /** * @brief Simple algorithm to convert epoch milliseconds to RTC time. * * Epoch milliseconds starts from 1970-1-1, 00:00:00.001 * * @param [out] tm rtc time * @param [in] epoch_millisec uint64_t number of milliseconds since epoch. * @return 0 success, otherwise failed. */ status_t epoch_ms_to_rtc(struct rtc_time *tm, uint64_t epoch_millisec); /** * @brief sdrv rtc enable. * * @param [in] dev sdrv rtc controller * @param [in] enable enable or disable * @return 0 success, otherwise failed. */ status_t sdrv_rtc_enable(sdrv_rtc_t *dev, bool enable); /** * @brief sdrv enable rtc wake up. * * @param [in] dev sdrv rtc controller * @param [in] type sdrv rtc wake up type * @param [in] enable enable or disable * @return 0 success, otherwise failed. */ status_t sdrv_rtc_wakeup_enable(sdrv_rtc_t *dev, sdrv_rtc_wakeup_enable_type_e type, bool enable); /** * @brief sdrv get rtc wake up status. * * @param [in] dev sdrv rtc controller * @return 1 wakeup, 0 not wakeup. */ bool sdrv_rtc_get_wakeup_status(sdrv_rtc_t *dev); /** * @brief sdrv clear rtc wake up status. * * @param [in] dev sdrv rtc controller * @return 0 success, otherwise failed. */ status_t sdrv_rtc_clear_wakeup_status(sdrv_rtc_t *dev); /** * @brief sdrv get rtc violation status. * * @param [in] dev sdrv rtc controller * @return 0 no violation, 1 overflow violation, 2 disable violation, 3 overflow & disable */ sdrv_rtc_violation_e sdrv_rtc_get_violation_status(sdrv_rtc_t *dev); /** * @brief sdrv rtc clear violation status. * * @param [in] dev sdrv rtc controller * @param [in] vio sdrv rtc violation type * @return 0 success, otherwise failed. */ status_t sdrv_rtc_clear_violation_status(sdrv_rtc_t *dev, sdrv_rtc_violation_e vio); /** * @brief sdrv rtc violation enable. * * @param [in] dev sdrv rtc controller * @param [in] vio_mask sdrv rtc violation type * @param [in] en violation enable or disable * @return 0 success, otherwise failed. */ status_t sdrv_rtc_violation_intr_enable(sdrv_rtc_t *dev, sdrv_rtc_violation_e vio, bool en); /** * @brief rtc get time * * Get current rtc time. * * @param [in] dev sdrv rtc controller * @param [in] tm rtc time * @return 0 success, otherwise failed. */ status_t sdrv_rtc_get_time(sdrv_rtc_t *dev, struct rtc_time *tm); /** * @brief rtc set time * * Set current rtc time. * * @param [in] dev sdrv rtc controller * @param [in] tm rtc time * @return 0 success, otherwise failed. */ status_t sdrv_rtc_set_time(sdrv_rtc_t *dev, struct rtc_time *tm); /** * @brief rtc get alarm * * Get rtc alarm time, rtc will trigger interrupt when rtc time arrives at alarm time. * * @param [in] dev sdrv rtc controller * @param [in] alrm rtc wakeup alarm infomation * @return 0 success, otherwise failed. */ status_t sdrv_rtc_get_alarm(sdrv_rtc_t *dev, struct rtc_wkalrm *alrm); /** * @brief rtc set alarm * * Set rtc alarm time, rtc will trigger interrupt when rtc time arrives at alarm time. * * @param [in] dev sdrv rtc controller * @param [in] alrm rtc wakeup alarm config * @return 0 success, otherwise failed. */ status_t sdrv_rtc_set_alarm(sdrv_rtc_t *dev, struct rtc_wkalrm *alrm); /** * @brief Enable rtc alarm. * * @param [in] dev sdrv rtc controller * @param [in] enable enable or disable * @return 0 success, otherwise failed. */ status_t sdrv_rtc_enable_alarm(sdrv_rtc_t *dev, bool enable); /** * @brief Enable rtc interrupt. * @param [in] source rtc wakeup/periodical/violation interrupt num. * @param [in] arg pointer to interrupt arg(rtc device structure). * @param [in] cb callback function. */ status_t sdrv_rtc_enable_it(uint32_t source, void *arg, rtc_cb_t cb); /** * @brief disable rtc interrput. * @param source rtc wakeup/periodical/violation interrupt num. * @return 0 success, otherwise failed. */ status_t sdrv_rtc_disable_it(uint32_t source); /** * @brief Read rtc general purpose register. * * Data in general purpose register will not be lost until RTC power down. * * @param [in] dev sdrv rtc controller * @param [in] gp_num sdrv general purpose register num * @return general purpose register value */ uint32_t sdrv_rtc_read_general_purpose_reg(sdrv_rtc_t *dev, sdrv_general_purpose_e gp_num); /** * @brief Write rtc general purpose register. * * @param [in] dev sdrv rtc controller * @param [in] gp_num sdrv general purpose register num * @param [in] value general purpose register value * @return 0 success, otherwise failed. */ status_t sdrv_rtc_write_general_purpose_reg(sdrv_rtc_t *dev, sdrv_general_purpose_e gp_num, uint32_t value); /** * @brief rtc lock. * * Once set rtc lock, rtc enable can not be changed until next power on reset. * * @param [in] dev sdrv rtc controller * @return 0 success, otherwise failed. */ status_t sdrv_rtc_lock(sdrv_rtc_t *dev); #endif /*_SDRV_RTC_H_*/