317 lines
7.2 KiB
C
317 lines
7.2 KiB
C
/**
|
|
* @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();
|
|
} |