新增所有文件
This commit is contained in:
759
drivers/source/rtc/sdrv_rtc.c
Normal file
759
drivers/source/rtc/sdrv_rtc.c
Normal file
@@ -0,0 +1,759 @@
|
||||
/**
|
||||
* @file sdrv_rtc.c
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: sec_rtc driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <irq.h>
|
||||
#include <irq_num.h>
|
||||
|
||||
#include "sdrv_rtc.h"
|
||||
#include "sdrv_rtc_reg.h"
|
||||
#include "udelay/udelay.h"
|
||||
|
||||
#define RTC_CLK_HZ (32 * 1024ul)
|
||||
#define RTC_CLK_SHIFT __builtin_ctz(RTC_CLK_HZ)
|
||||
#define RTC_TICK_TO_SECOND(t) ((t) >> RTC_CLK_SHIFT)
|
||||
#define RTC_SECOND_TO_TICK(s) ((s) << RTC_CLK_SHIFT)
|
||||
#define RTC_TICK_TO_MILLISECOND(t) ((uint64_t)(t) * 1000 / 32768)
|
||||
#define RTC_MILLISECOND_TO_TICK(s) ((uint64_t)(s) * 32768 / 1000)
|
||||
|
||||
#define DELAY_US 240
|
||||
|
||||
#define SECONDS_PER_MINUTE (60ul)
|
||||
#define MINUTES_PER_HOUR (60ul)
|
||||
#define HOURS_PER_DAY (24ul)
|
||||
#define SECONDS_PER_HOUR (SECONDS_PER_MINUTE * MINUTES_PER_HOUR)
|
||||
#define SECONDS_PER_DAY (SECONDS_PER_HOUR * HOURS_PER_DAY)
|
||||
|
||||
#define LEAP_YEAR_DAYS (366ul)
|
||||
#define COMMON_YEAR_DAYS (365ul)
|
||||
|
||||
#define TM_START_YEAR (1900ul)
|
||||
#define EPOCH_START_YEAR (1970ul)
|
||||
static const uint32_t month_days[12] = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief check RTC time is valid.
|
||||
*
|
||||
* @param [in] tm RTC time.
|
||||
* @return 0 success, otherwise failed.
|
||||
*/
|
||||
static status_t sdrv_check_rtc_time(struct rtc_time *tm)
|
||||
{
|
||||
if (tm->tm_subsec > 999u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if (tm->tm_sec > 61u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if (tm->tm_min > 59u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if (tm->tm_hour > 23u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if ((tm->tm_mday < 1u) || (tm->tm_mday > 31u)) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if (tm->tm_mon > 11u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if (tm->tm_wday > 6u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
if (tm->tm_year > 365u) {
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
uint64_t epoch_sec = 0;
|
||||
uint32_t year = tm->tm_year + TM_START_YEAR;
|
||||
|
||||
if (sdrv_check_rtc_time(tm) < 0) {
|
||||
ssdk_printf(SSDK_WARNING, "%s invalid rtc time!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint32_t num = EPOCH_START_YEAR; num < year; num++) {
|
||||
epoch_sec += SECONDS_PER_DAY *
|
||||
(is_leap_year(num) ? LEAP_YEAR_DAYS : COMMON_YEAR_DAYS);
|
||||
}
|
||||
|
||||
for (uint32_t num = 0; num < tm->tm_mon; num++) {
|
||||
epoch_sec += month_days[num] * SECONDS_PER_DAY;
|
||||
|
||||
if (is_leap_year(year) && (num == 1)) {
|
||||
epoch_sec += SECONDS_PER_DAY;
|
||||
}
|
||||
}
|
||||
|
||||
epoch_sec += (tm->tm_mday - 1) * SECONDS_PER_DAY;
|
||||
epoch_sec += tm->tm_hour * SECONDS_PER_HOUR;
|
||||
epoch_sec += tm->tm_min * SECONDS_PER_MINUTE;
|
||||
epoch_sec += tm->tm_sec;
|
||||
|
||||
return epoch_sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simple algorithm to convert epoch seconds to RTC time.
|
||||
*
|
||||
* Epoch seconds starts from 1970-1-1, 00:00:01
|
||||
*
|
||||
* @param [out] tm
|
||||
* @param [in] epoch_sec
|
||||
*/
|
||||
status_t epoch_to_rtc(struct rtc_time *tm, uint64_t epoch_sec)
|
||||
{
|
||||
uint32_t year = EPOCH_START_YEAR;
|
||||
uint32_t month = 0;
|
||||
uint32_t days = epoch_sec / SECONDS_PER_DAY;
|
||||
uint32_t seconds;
|
||||
|
||||
tm->tm_wday = (4 + days) % 7;
|
||||
|
||||
while (days >= COMMON_YEAR_DAYS) {
|
||||
if (is_leap_year(year)) {
|
||||
if (days >= LEAP_YEAR_DAYS) {
|
||||
days -= LEAP_YEAR_DAYS;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
days -= COMMON_YEAR_DAYS;
|
||||
}
|
||||
|
||||
year++;
|
||||
}
|
||||
|
||||
tm->tm_year = year - TM_START_YEAR;
|
||||
|
||||
while (days >= 28) {
|
||||
if (is_leap_year(year) && (month == 1)) {
|
||||
if (days >= 29) {
|
||||
days -= 29;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (days >= month_days[month]) {
|
||||
days -= month_days[month];
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
month++;
|
||||
}
|
||||
|
||||
tm->tm_mon = month;
|
||||
tm->tm_mday = days + 1;
|
||||
|
||||
seconds = epoch_sec % SECONDS_PER_DAY;
|
||||
tm->tm_hour = seconds / 3600;
|
||||
tm->tm_min = (seconds % 3600) / 60;
|
||||
tm->tm_sec = (seconds % 3600) % 60;
|
||||
|
||||
return sdrv_check_rtc_time(tm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
uint64_t epoch_millisec = 0;
|
||||
uint32_t year = tm->tm_year + TM_START_YEAR;
|
||||
|
||||
if (sdrv_check_rtc_time(tm) < 0) {
|
||||
ssdk_printf(SSDK_WARNING, "%s invalid rtc time!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint32_t num = EPOCH_START_YEAR; num < year; num++) {
|
||||
epoch_millisec += (uint64_t)SECONDS_PER_DAY * 1000 *
|
||||
(is_leap_year(num) ? LEAP_YEAR_DAYS : COMMON_YEAR_DAYS);
|
||||
}
|
||||
|
||||
for (uint32_t num = 0; num < tm->tm_mon; num++) {
|
||||
epoch_millisec += (uint64_t)month_days[num] * SECONDS_PER_DAY * 1000;
|
||||
|
||||
if (is_leap_year(year) && (num == 1)) {
|
||||
epoch_millisec += SECONDS_PER_DAY * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
epoch_millisec += (uint64_t)(tm->tm_mday - 1) * SECONDS_PER_DAY * 1000;
|
||||
epoch_millisec += (uint64_t)tm->tm_hour * SECONDS_PER_HOUR * 1000;
|
||||
epoch_millisec += (uint64_t)tm->tm_min * SECONDS_PER_MINUTE * 1000;
|
||||
epoch_millisec += (uint64_t)tm->tm_sec * 1000;
|
||||
epoch_millisec += (uint64_t)tm->tm_subsec;
|
||||
|
||||
return epoch_millisec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simple algorithm to convert epoch milliseconds to RTC time.
|
||||
*
|
||||
* Epoch milliseconds starts from 1970-1-1, 00:00:00.001
|
||||
*
|
||||
* @param [out] tm
|
||||
* @param [in] epoch_sec
|
||||
*/
|
||||
status_t epoch_ms_to_rtc(struct rtc_time *tm, uint64_t epoch_millisec)
|
||||
{
|
||||
uint32_t year = EPOCH_START_YEAR;
|
||||
uint32_t month = 0;
|
||||
uint32_t days = epoch_millisec / SECONDS_PER_DAY / 1000;
|
||||
uint32_t seconds;
|
||||
|
||||
tm->tm_wday = (4 + days) % 7;
|
||||
|
||||
while (days >= COMMON_YEAR_DAYS) {
|
||||
if (is_leap_year(year)) {
|
||||
if (days >= LEAP_YEAR_DAYS) {
|
||||
days -= LEAP_YEAR_DAYS;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
days -= COMMON_YEAR_DAYS;
|
||||
}
|
||||
|
||||
year++;
|
||||
}
|
||||
|
||||
tm->tm_year = year - TM_START_YEAR;
|
||||
|
||||
while (days >= 28) {
|
||||
if (is_leap_year(year) && (month == 1)) {
|
||||
if (days >= 29) {
|
||||
days -= 29;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (days >= month_days[month]) {
|
||||
days -= month_days[month];
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
month++;
|
||||
}
|
||||
|
||||
tm->tm_mon = month;
|
||||
tm->tm_mday = days + 1;
|
||||
|
||||
seconds = (epoch_millisec % (SECONDS_PER_DAY * 1000)) / 1000;
|
||||
tm->tm_hour = seconds / 3600;
|
||||
tm->tm_min = (seconds % 3600) / 60;
|
||||
tm->tm_sec = (seconds % 3600) % 60;
|
||||
tm->tm_subsec = epoch_millisec % 1000;
|
||||
|
||||
return sdrv_check_rtc_time(tm);
|
||||
}
|
||||
|
||||
static status_t _rtc_handler(uint32_t source, void *arg)
|
||||
{
|
||||
sdrv_rtc_t *dev = arg;
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
sdrv_rtc_violation_e vio_status;
|
||||
|
||||
/* disable overflow/disable violation intr */
|
||||
if (source == dev->violation_intr) {
|
||||
vio_status = sdrv_rtc_get_violation_status(dev);
|
||||
|
||||
if (dev->vio_mask & vio_status) {
|
||||
sdrv_rtc_violation_intr_enable(dev, (sdrv_rtc_violation_e)(dev->vio_mask & vio_status), false);
|
||||
}
|
||||
}
|
||||
else if (source == dev->wakeup_intr) {
|
||||
sec_rtc_wakeup_enable(rtc,
|
||||
BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE | BM_WAKEUP_CTRL_REQ_ENABLE,
|
||||
false);
|
||||
}
|
||||
|
||||
if (dev->cb)
|
||||
dev->cb(source, arg);
|
||||
|
||||
/* overflow/disable violation intr */
|
||||
if (source == dev->violation_intr) {
|
||||
sdrv_rtc_clear_violation_status(dev, vio_status);
|
||||
|
||||
if (dev->vio_mask & vio_status) {
|
||||
sdrv_rtc_violation_intr_enable(dev, (sdrv_rtc_violation_e)(dev->vio_mask & vio_status), true);
|
||||
}
|
||||
}
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
int ret;
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
ret = sec_rtc_local_enable(rtc, enable);
|
||||
|
||||
if (ret < 0) {
|
||||
ssdk_printf(SSDK_ERR, "%s sec rtc enable faild!\n", __func__);
|
||||
return SDRV_RTC_STATUS_LOCK;
|
||||
}
|
||||
|
||||
udelay(DELAY_US);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
uint8_t vtype = 0;
|
||||
|
||||
switch (type) {
|
||||
case SDRV_WKUP_ENABLE:
|
||||
vtype = BM_WAKEUP_CTRL_ENABLE;
|
||||
break;
|
||||
|
||||
case SDRV_WKUP_ENABLE_IRQ:
|
||||
vtype = BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE;
|
||||
break;
|
||||
|
||||
case SDRV_WKUP_ENABLE_REQ:
|
||||
vtype = BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_REQ_ENABLE;
|
||||
break;
|
||||
|
||||
case SDRV_WKUP_ENABLE_ALL:
|
||||
vtype = BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE |
|
||||
BM_WAKEUP_CTRL_REQ_ENABLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
vtype = BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE |
|
||||
BM_WAKEUP_CTRL_REQ_ENABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
sec_rtc_wakeup_enable(rtc, vtype, enable);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
return sec_rtc_get_wakeup_status(rtc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* rtc wakeup status has been cleared */
|
||||
if (!sdrv_rtc_get_wakeup_status(dev)) {
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
|
||||
if (sec_rtc_is_alarm_enable(rtc)) {
|
||||
sec_rtc_wakeup_enable(rtc,
|
||||
BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE | BM_WAKEUP_CTRL_REQ_ENABLE,
|
||||
false);
|
||||
}
|
||||
|
||||
sec_rtc_clear_wakeup_status(rtc);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
return (sdrv_rtc_violation_e)sec_rtc_get_violation_status(rtc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sdrv clear rtc violation status.
|
||||
*
|
||||
* @param [in] dev sdrv rtc controller
|
||||
* @return 0 success, otherwise failed.
|
||||
*/
|
||||
status_t sdrv_rtc_clear_violation_status(sdrv_rtc_t *dev,
|
||||
sdrv_rtc_violation_e vio)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
sec_rtc_clear_violation_status(rtc, vio);
|
||||
|
||||
if (vio & SDRV_RTC_VIO_OVERFLOW) {
|
||||
sec_rtc_set_cross_clk_en(rtc);
|
||||
}
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
|
||||
if (en) {
|
||||
sec_rtc_set_violation_enable(rtc, vio);
|
||||
}
|
||||
else {
|
||||
sec_rtc_set_violation_disable(rtc, vio);
|
||||
}
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
sdrv_rtc_t *dev = arg;
|
||||
dev->cb = cb;
|
||||
|
||||
if (source > 0) {
|
||||
irq_attach(source, (irq_handler)_rtc_handler, dev);
|
||||
irq_enable(source);
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (source > 0) {
|
||||
irq_detach(source);
|
||||
irq_disable(source);
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief rtc get time
|
||||
*
|
||||
* Get current rtc time.
|
||||
*
|
||||
* @param [in] dev sdrv rtc controller
|
||||
* @param [in] tm
|
||||
* @return 0 success, otherwise failed.
|
||||
*/
|
||||
status_t sdrv_rtc_get_time(sdrv_rtc_t *dev, struct rtc_time *tm)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
uint64_t millisecs = RTC_TICK_TO_MILLISECOND(sec_rtc_get_tick(rtc));
|
||||
|
||||
return epoch_ms_to_rtc(tm, millisecs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief rtc set time
|
||||
*
|
||||
* Set current rtc time.
|
||||
*
|
||||
* @param [in] dev
|
||||
* @param [in] tm
|
||||
* @return 0 success, otherwise failed.
|
||||
*/
|
||||
status_t sdrv_rtc_set_time(sdrv_rtc_t *dev, struct rtc_time *tm)
|
||||
{
|
||||
uint64_t millisecs = rtc_to_epoch_ms(tm);
|
||||
int ret;
|
||||
|
||||
if (millisecs == 0) {
|
||||
ssdk_printf(SSDK_WARNING, "%s default set rtc time 1970-1-1 00:00:00.000\n", __func__);
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
ret = sec_rtc_local_enable(rtc, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
ssdk_printf(SSDK_ERR, "%s sec rtc disable failed!\n", __func__);
|
||||
return SDRV_RTC_STATUS_LOCK;
|
||||
}
|
||||
|
||||
/* writing RTC_L/H, extra waitting 2*240us */
|
||||
udelay(DELAY_US);
|
||||
|
||||
sec_rtc_set_tick(rtc, RTC_MILLISECOND_TO_TICK(millisecs));
|
||||
sec_rtc_set_cross_clk_en(rtc);
|
||||
|
||||
ret = sec_rtc_local_enable(rtc, 1);
|
||||
|
||||
if (ret < 0) {
|
||||
ssdk_printf(SSDK_ERR, "%s sec rtc enable failed!\n", __func__);
|
||||
return SDRV_RTC_STATUS_LOCK;
|
||||
}
|
||||
|
||||
udelay(DELAY_US);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief rtc get alarm
|
||||
*
|
||||
* Get rtc alarm time, rtc will trigger interrupt when rtc time arrives at alarm time.
|
||||
*
|
||||
* @param [in] dev
|
||||
* @param [in] alrm
|
||||
* @return 0
|
||||
*/
|
||||
status_t sdrv_rtc_get_alarm(sdrv_rtc_t *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
status_t ret = SDRV_STATUS_FAIL;
|
||||
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
uint64_t millisecs = RTC_TICK_TO_MILLISECOND(sec_rtc_get_alarm_tick(rtc));
|
||||
|
||||
ret = epoch_ms_to_rtc(&alrm->tm, millisecs);
|
||||
alrm->enable = sec_rtc_is_alarm_enable(rtc);
|
||||
alrm->pending = sec_rtc_get_wakeup_status(rtc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @return 0 success, otherwise failed.
|
||||
*/
|
||||
status_t sdrv_rtc_set_alarm(sdrv_rtc_t *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
uint64_t millisecs = rtc_to_epoch_ms(&alrm->tm);
|
||||
|
||||
if (millisecs == 0) {
|
||||
ssdk_printf(SSDK_ERR, "%s sec rtc set sec failed!\n", __func__);
|
||||
return SDRV_RTC_STATUS_INVALID_RTC_TIME;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
sec_rtc_set_alarm_tick(rtc, RTC_MILLISECOND_TO_TICK(millisecs));
|
||||
sec_rtc_set_cross_clk_en(rtc);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
|
||||
sec_rtc_wakeup_enable(rtc,
|
||||
BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE | BM_WAKEUP_CTRL_REQ_ENABLE,
|
||||
enable);
|
||||
|
||||
if (!enable) {
|
||||
sec_rtc_clear_wakeup_status(rtc);
|
||||
}
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
|
||||
return sec_rtc_read_general_purpose_reg(rtc, 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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
sec_rtc_write_general_purpose_reg(rtc, gp_num, value);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (dev->base == 0) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
Rtc *rtc = (Rtc *)dev->base;
|
||||
sec_rtc_lock(rtc);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
317
drivers/source/rtc/sdrv_rtc_reg.c
Normal file
317
drivers/source/rtc/sdrv_rtc_reg.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @file sdrv_rtc_reg.c
|
||||
* @brief semidrive sec_rtc driver
|
||||
*
|
||||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*/
|
||||
#include <types.h>
|
||||
#include <part.h>
|
||||
#include <sdrv_ckgen.h>
|
||||
|
||||
#include "sdrv_rtc_reg.h"
|
||||
#include "reg.h"
|
||||
#include "bits.h"
|
||||
#include "udelay/udelay.h"
|
||||
|
||||
#if CONFIG_RTC_SS_DYNAMIC_PCLK
|
||||
#define RTC_SS_ACCESS_DELAY_CYCLE(n) udelay(35 * n)
|
||||
#else
|
||||
#define RTC_SS_ACCESS_DELAY_CYCLE(n)
|
||||
#endif
|
||||
|
||||
uint64_t sec_rtc_get_tick(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
RTC_SS_ACCESS_DELAY_CYCLE(1);
|
||||
uint64_t tick = rtc->RTC_L;
|
||||
|
||||
tick = (uint64_t)(rtc->RTC_H_HOLD_SHADOW) << 32;
|
||||
tick |= rtc->RTC_L_HOLD_SHADOW;
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
void sec_rtc_set_tick(Rtc *rtc, uint64_t v)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
uint32_t tick = v & 0xffffffff;
|
||||
rtc->RTC_L = tick;
|
||||
rtc->RTC_H = (v >> 32) & 0xffff;
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
|
||||
void sec_rtc_lock(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->SEC_RTC_CTRL |= BM_SEC_RTC_CTRL_LOCK;
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
|
||||
bool sec_rtc_is_locked(Rtc *rtc)
|
||||
{
|
||||
bool locked = false;
|
||||
|
||||
if (rtc->SEC_RTC_CTRL & BM_SEC_RTC_CTRL_LOCK)
|
||||
locked = true;
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
||||
int sec_rtc_local_enable(Rtc *rtc, bool en)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
if (!sec_rtc_is_locked(rtc)) {
|
||||
if (en)
|
||||
rtc->SEC_RTC_CTRL |= BM_SEC_RTC_CTRL_RTC_LOCAL_ENABLE;
|
||||
else
|
||||
rtc->SEC_RTC_CTRL &= ~BM_SEC_RTC_CTRL_RTC_LOCAL_ENABLE;
|
||||
|
||||
RTC_SS_ACCESS_END();
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTC_SS_ACCESS_END();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void sec_rtc_set_alarm_tick(Rtc *rtc, uint64_t val)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->TIMER_L = (uint32_t)(val & 0xffffffff);
|
||||
rtc->TIMER_H = (val >> 32) & 0xffff;
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
|
||||
uint64_t sec_rtc_get_alarm_tick(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
uint64_t tick = (uint64_t)(rtc->TIMER_H) << 32;
|
||||
tick |= rtc->TIMER_L;
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
uint8_t sec_rtc_is_alarm_enable(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
uint32_t val = rtc->WAKEUP_CTRL;
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return (val & (BM_WAKEUP_CTRL_ENABLE | BM_WAKEUP_CTRL_IRQ_ENABLE |
|
||||
BM_WAKEUP_CTRL_REQ_ENABLE));
|
||||
}
|
||||
|
||||
bool sec_rtc_get_wakeup_status(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
if (rtc->WAKEUP_CTRL & BM_WAKEUP_CTRL_STATUS) {
|
||||
RTC_SS_ACCESS_END();
|
||||
return true;
|
||||
}
|
||||
|
||||
RTC_SS_ACCESS_END();
|
||||
return false;
|
||||
}
|
||||
|
||||
void sec_rtc_clear_wakeup_status(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->WAKEUP_CTRL |= BM_WAKEUP_CTRL_CLEAR;
|
||||
RTC_SS_ACCESS_END();
|
||||
sec_rtc_set_cross_clk_en(rtc);
|
||||
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->WAKEUP_CTRL &= ~BM_WAKEUP_CTRL_CLEAR;
|
||||
RTC_SS_ACCESS_END();
|
||||
sec_rtc_set_cross_clk_en(rtc);
|
||||
}
|
||||
|
||||
bool sec_rtc_get_overflow_status(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
if (rtc->WAKEUP_CTRL & BM_WAKEUP_CTRL_STATUS) {
|
||||
RTC_SS_ACCESS_END();
|
||||
return true;
|
||||
}
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sec_rtc_clear_violation_status(Rtc *rtc, uint8_t vio)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->VIOLATION_INT = (rtc->VIOLATION_INT & ~BM_VIOLATION_INT_DISABLE_STATUS) |
|
||||
(vio << BM_VIOLATION_INT_OVERFLOW_STATS_BIT);
|
||||
|
||||
rtc->WAKEUP_CTRL |= (vio << BM_WAKEUP_CTRL_OVERFLOW_CLEAR_BIT);
|
||||
udelay(150);
|
||||
|
||||
rtc->WAKEUP_CTRL &= ~(vio << BM_WAKEUP_CTRL_OVERFLOW_CLEAR_BIT);
|
||||
udelay(150);
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
|
||||
uint64_t sec_rtc_get_hld_tick(Rtc *rtc, uint64_t *tick)
|
||||
{
|
||||
if (tick)
|
||||
*tick = sec_rtc_get_tick(rtc);
|
||||
|
||||
RTC_SS_ACCESS_START();
|
||||
uint64_t tick_hld = (uint64_t)(rtc->RTC_H_HOLD_SHADOW) << 32;
|
||||
tick_hld |= rtc->RTC_L_HOLD_SHADOW;
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return tick_hld;
|
||||
}
|
||||
|
||||
void sec_rtc_set_rtc_ctrl(Rtc *rtc, uint32_t ctrl)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->SEC_RTC_CTRL = ctrl;
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
|
||||
void sec_rtc_set_cross_clk_en(Rtc *rtc)
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->RTC_REGISTER_CROSS_CLOCK |=
|
||||
BM_RTC_REGISTER_CROSS_CLOCK_REGISTER_CROSS_CLOCK_EN;
|
||||
|
||||
udelay(120);
|
||||
|
||||
while ((rtc->RTC_REGISTER_CROSS_CLOCK &
|
||||
BM_RTC_REGISTER_CROSS_CLOCK_REGISTER_CROSS_CLOCK_EN)
|
||||
&& (cnt < 120)) {
|
||||
udelay(1);
|
||||
cnt ++;
|
||||
};
|
||||
RTC_SS_ACCESS_END();
|
||||
udelay(120);
|
||||
}
|
||||
|
||||
void sec_rtc_wakeup_enable(Rtc *rtc, uint8_t vtype, uint8_t en)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
uint32_t v = rtc->WAKEUP_CTRL;
|
||||
|
||||
if (en)
|
||||
v |= vtype;
|
||||
else
|
||||
v &= ~vtype;
|
||||
|
||||
rtc->WAKEUP_CTRL = v;
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
sec_rtc_set_cross_clk_en(rtc);
|
||||
}
|
||||
|
||||
void sec_rtc_ms_cfg(Rtc *master, Rtc *slave, uint8_t ctmode1, uint8_t ctmode2)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
master->RTC_WORKING_MODE = BM_RTC_WORKING_MODE_RTC_MASTER_SLAVE;
|
||||
|
||||
if (ctmode1)
|
||||
master->RTC_WORKING_MODE |= BM_RTC_WORKING_MODE_RTC_COUNT_MODE;
|
||||
|
||||
slave->RTC_WORKING_MODE &= ~BM_RTC_WORKING_MODE_RTC_MASTER_SLAVE;
|
||||
|
||||
if (ctmode2)
|
||||
slave->RTC_WORKING_MODE |= BM_RTC_WORKING_MODE_RTC_COUNT_MODE;
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
|
||||
void sec_rtc_set_violation_enable(Rtc *rtc, uint8_t mask)
|
||||
{
|
||||
if (rtc) {
|
||||
/* do not clear BM_VIOLATION_INT_DISABLE_STATUS */
|
||||
RTC_SS_ACCESS_START();
|
||||
rtc->VIOLATION_INT = (rtc->VIOLATION_INT & ~BM_VIOLATION_INT_DISABLE_STATUS) |
|
||||
FV_VIOLATION_INT_MASK(mask);
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
}
|
||||
|
||||
void sec_rtc_set_violation_disable(Rtc *rtc, uint8_t mask)
|
||||
{
|
||||
if (rtc) {
|
||||
RTC_SS_ACCESS_START();
|
||||
/* do not clear BM_VIOLATION_INT_DISABLE_STATUS */
|
||||
rtc->VIOLATION_INT &= (~FV_VIOLATION_INT_MASK(mask) &
|
||||
~BM_VIOLATION_INT_DISABLE_STATUS);
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sec_rtc_get_violation_status(Rtc *rtc)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
uint32_t val = rtc->VIOLATION_INT;
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return ((val & (BM_VIOLATION_INT_OVERFLOW_STATS |
|
||||
BM_VIOLATION_INT_DISABLE_STATUS))
|
||||
>> BM_VIOLATION_INT_OVERFLOW_STATS_BIT);
|
||||
}
|
||||
|
||||
uint32_t sec_rtc_read_general_purpose_reg(Rtc *rtc, uint8_t gp_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
RTC_SS_ACCESS_START();
|
||||
switch (gp_num) {
|
||||
case 0:
|
||||
ret = rtc->GP0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ret = rtc->GP1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ret = rtc->GP2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ret = rtc->GP3;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = rtc->GP0;
|
||||
break;
|
||||
}
|
||||
RTC_SS_ACCESS_END();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sec_rtc_write_general_purpose_reg(Rtc *rtc, uint8_t gp_num, uint32_t value)
|
||||
{
|
||||
RTC_SS_ACCESS_START();
|
||||
switch (gp_num) {
|
||||
case 0:
|
||||
rtc->GP0 = value;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rtc->GP1 = value;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
rtc->GP2 = value;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rtc->GP3 = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
rtc->GP0 = value;
|
||||
break;
|
||||
}
|
||||
RTC_SS_ACCESS_END();
|
||||
}
|
||||
106
drivers/source/rtc/sdrv_rtc_reg.h
Normal file
106
drivers/source/rtc/sdrv_rtc_reg.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file sdrv_rtc_reg.h
|
||||
* @brief sdrv rtc_reg api header.
|
||||
*
|
||||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*/
|
||||
#ifndef _SDRV_RTC_REG_H_
|
||||
#define _SDRV_RTC_REG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define __I volatile /**< Defines 'read-only' permissions */
|
||||
#else
|
||||
#define __I volatile const /**< Defines 'read-only' permissions */
|
||||
#endif
|
||||
#define __O volatile /**< Defines 'write-only' permissions */
|
||||
#define __IO volatile /**< Defines 'read/write' permissions */
|
||||
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef struct {
|
||||
__IO uint32_t SEC_RTC_CTRL; /*offset 0*/
|
||||
__IO uint32_t RTC_H; /*offset 4*/
|
||||
__IO uint32_t RTC_L; /*offset 8*/
|
||||
__IO uint32_t AUTO_ADJUST; /*offset c*/
|
||||
__IO uint32_t TIMER_H; /*offset 10*/
|
||||
__IO uint32_t TIMER_L; /*offset 14*/
|
||||
__IO uint32_t WAKEUP_CTRL; /*offset 18*/
|
||||
__IO uint32_t PERIODICAL_CTRL; /*offset 1c*/
|
||||
__IO uint32_t VIOLATION_INT; /*offset 20*/
|
||||
__IO uint32_t APB_MONITOR_ERR_INJ_EN; /*offset 24*/
|
||||
__IO uint32_t APB_MONITOR_ERR_INJ_ECC; /*offset 28*/
|
||||
__IO uint32_t APB_MONITOR_ERR_INJ_WDATA; /*offset 2C*/
|
||||
__IO uint32_t SAFETY_ERR_IRQ_STAT; /*offset 0x30*/
|
||||
__IO uint32_t SAFETY_ERR_IRQ_STAT_EN; /*offset 0x34*/
|
||||
__IO uint32_t SAFETY_ERR_IRQ_SIG_EN; /*offset 0x38*/
|
||||
__IO uint32_t IRQ_ERR_INJ; /*offset 0x3C*/
|
||||
__IO uint32_t IRQ_ERR_EJ_EN; /*offset 0x40*/
|
||||
__IO uint32_t GP0; /*offset 0x44*/
|
||||
__IO uint32_t GP1; /*offset 0X48*/
|
||||
__IO uint32_t GP2; /*offset 0x4c*/
|
||||
__IO uint32_t GP3; /*offset 0x50*/
|
||||
__IO uint32_t RTC_H_HOLD_SHADOW; /*offset 0x54*/
|
||||
__IO uint32_t RTC_L_HOLD_SHADOW; /*offset 0x58*/
|
||||
__IO uint32_t RTC_WORKING_MODE; /*offset 0x5c*/
|
||||
__IO uint32_t RTC_REGISTER_CROSS_CLOCK; /*offset 60*/
|
||||
__IO uint32_t RTC_PARITY_ERR_INT_STAT; /*offset 0x64*/
|
||||
__IO uint32_t RTC_PARITY_ERR_INT_STAT_EN; /*offset 0x68*/
|
||||
__IO uint32_t RTC_PARITY_ERR_INT_SIG_EN; /*offset 0x6c*/
|
||||
__IO uint32_t PRDATAINJ; /*offset 0x70*/
|
||||
__IO uint32_t RTC_OUT_ERR_INJ; /*offset 0x74*/
|
||||
} Rtc;
|
||||
#endif
|
||||
|
||||
#define BM_SEC_RTC_CTRL_LOCK (0x01U << 31U)
|
||||
#define BM_SEC_RTC_CTRL_RTC_LOCAL_ENABLE (0x01U << 0U)
|
||||
#define BM_WAKEUP_CTRL_STATUS (0x01U << 3U)
|
||||
#define BM_WAKEUP_CTRL_ENABLE (0x01U << 0U)
|
||||
#define BM_WAKEUP_CTRL_IRQ_ENABLE (0x01U << 1U)
|
||||
#define BM_WAKEUP_CTRL_REQ_ENABLE (0x01U << 2U)
|
||||
#define BM_WAKEUP_CTRL_CLEAR (0x01U << 4U)
|
||||
#define BM_SEC_RTC_CTRL_SECURE_ENABLE (0x01U << 1U)
|
||||
#define BM_SEC_RTC_CTRL_PRIVILEGE_ENABLE (0x01U << 2U)
|
||||
#define BM_RTC_REGISTER_CROSS_CLOCK_REGISTER_CROSS_CLOCK_EN (0x01U << 0U)
|
||||
#define BM_WAKEUP_CTRL_OVERFLOW_CLEAR_BIT (5U)
|
||||
#define BM_WAKEUP_CTRL_DISABLE_CLEAR_BIT (6U)
|
||||
#define BM_RTC_WORKING_MODE_RTC_MASTER_SLAVE (0x01U << 0U)
|
||||
#define BM_RTC_WORKING_MODE_RTC_COUNT_MODE (0x01U << 1U)
|
||||
#define BM_VIOLATION_INT_OVERFLOW_STATS (0x01U << 2U)
|
||||
#define BM_VIOLATION_INT_OVERFLOW_STATS_BIT (2U)
|
||||
#define BM_PERIODICAL_CRTL_IRQ_ENABLE (0x01U << 0U)
|
||||
#define BM_VIOLATION_INT_DISABLE_STATUS (0x01U << 3U)
|
||||
#define FM_VIOLATION_INT_MASK (0x3U << 0U)
|
||||
#define FV_VIOLATION_INT_MASK(v) \
|
||||
(((v) << 0U) & FM_VIOLATION_INT_MASK)
|
||||
|
||||
#define FM_PERIODICAL_CRTL_FREQ (0xfU << 3U)
|
||||
#define FV_PERIODICAL_CRTL_FREQ(v) \
|
||||
(((v) << 3U) & FM_PERIODICAL_CRTL_FREQ)
|
||||
|
||||
#define FM_PERIODICAL_CRTL_FREQ (0xfU << 3U)
|
||||
#define GFV_PERIODICAL_CRTL_FREQ(v) \
|
||||
(((v) & FM_PERIODICAL_CRTL_FREQ) >> 3U)
|
||||
|
||||
void sec_rtc_set_cross_clk_en(Rtc *rtc);
|
||||
void sec_rtc_set_rtc_ctrl(Rtc *rtc, uint32_t ctrl);
|
||||
void sec_rtc_wakeup_enable(Rtc *rtc, uint8_t vtype, uint8_t en);
|
||||
void sec_rtc_clear_wakeup_status(Rtc *rtc);
|
||||
void sec_rtc_clear_violation_status(Rtc *rtc, uint8_t vio);
|
||||
void sec_rtc_set_violation_enable(Rtc *rtc, uint8_t mask);
|
||||
void sec_rtc_set_violation_disable(Rtc *rtc, uint8_t mask);
|
||||
uint64_t sec_rtc_get_tick(Rtc *rtc);
|
||||
uint8_t sec_rtc_get_violation_status(Rtc *rtc);
|
||||
void sec_rtc_enable_periodical(Rtc *rtc, uint8_t en);
|
||||
int sec_rtc_local_enable(Rtc *rtc, bool en);
|
||||
void sec_rtc_set_tick(Rtc *rtc, uint64_t v);
|
||||
uint64_t sec_rtc_get_alarm_tick(Rtc *rtc);
|
||||
uint8_t sec_rtc_is_alarm_enable(Rtc *rtc);
|
||||
bool sec_rtc_get_wakeup_status(Rtc *rtc);
|
||||
void sec_rtc_set_alarm_tick(Rtc *rtc, uint64_t val);
|
||||
uint64_t sec_rtc_get_hld_tick(Rtc *rtc, uint64_t *tick);
|
||||
uint32_t sec_rtc_read_general_purpose_reg(Rtc *rtc, uint8_t gp_num);
|
||||
void sec_rtc_write_general_purpose_reg(Rtc *rtc, uint8_t gp_num, uint32_t value);
|
||||
void sec_rtc_lock(Rtc *rtc);
|
||||
#endif /*_SDRV_RTC_REG_H_*/
|
||||
Reference in New Issue
Block a user