270 lines
5.6 KiB
C
270 lines
5.6 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "common.h"
|
|
#include "vrtc.h"
|
|
#include "timer_source.h"
|
|
#include "register.h"
|
|
#include "FreeRTOS.h"
|
|
#include "mailbox-api.h"
|
|
#include "timers.h"
|
|
#include "suspend.h"
|
|
#include "soc.h"
|
|
#include "string.h"
|
|
#include "semphr.h"
|
|
#include "stick_mem.h"
|
|
#include "interrupt_control_eclic.h"
|
|
|
|
#define RTC_ALARM_MAX \
|
|
((uint32_t)((uint64_t)((TickType_t)~(TickType_t)0) * 1000 / configTICK_RATE_HZ / 1000))
|
|
|
|
#undef TAG
|
|
#define TAG "VRTC"
|
|
|
|
#ifdef VRTC_DEBUG
|
|
#define VRTC_DBG(...) printf(__VA_ARGS__)
|
|
#else
|
|
#define VRTC_DBG(...)
|
|
#endif
|
|
|
|
static uint32_t ulCurTime, ulBaseTime;
|
|
static TimerHandle_t xRTCUpdTimer;
|
|
|
|
static void prvRtcSet(uint32_t ulValue)
|
|
{
|
|
taskENTER_CRITICAL();
|
|
#ifdef CONFIG_STICK_MEM
|
|
if (stick_mem_write(STICK_VRTC, ulValue))
|
|
printf("[%s]: set vrtc failed\n", TAG);
|
|
#else
|
|
REG32(VRTC_STICKY_REG) = ulValue;
|
|
|
|
#endif
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
static void prvRtcGet(uint32_t *ulValue)
|
|
{
|
|
taskENTER_CRITICAL();
|
|
#ifdef CONFIG_STICK_MEM
|
|
if (stick_mem_read(STICK_VRTC, (unsigned int *)ulValue))
|
|
printf("[%s]: get vrtc failed\n", TAG);
|
|
#else
|
|
*ulValue = REG32(VRTC_STICKY_REG);
|
|
#endif
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
static void prvRtcSecToTm(uint32_t sec, struct rtc_time *tm)
|
|
{
|
|
uint32_t min;
|
|
|
|
tm->tm_sec = sec % 60;
|
|
min = sec / 60;
|
|
tm->tm_min = min % 60;
|
|
}
|
|
|
|
void vPoweroffGetRtcMinSec(char *time)
|
|
{
|
|
uint32_t secs;
|
|
struct rtc_time tm;
|
|
|
|
if (power_mode == 0xf) {
|
|
prvRtcGet(&secs);
|
|
prvRtcSecToTm(secs, &tm);
|
|
|
|
sprintf(time, "%02d", tm.tm_min);
|
|
sprintf(time+2, "%02d", tm.tm_sec);
|
|
} else {
|
|
printf("not poweroff mode, invalid called!\n");
|
|
time = NULL;
|
|
}
|
|
}
|
|
|
|
static void prvRtcUpdHandler(TimerHandle_t xTimer)
|
|
{
|
|
(void)xTimer;
|
|
|
|
ulCurTime += (timere_read() - ulBaseTime);
|
|
ulBaseTime = timere_read();
|
|
prvRtcSet(ulCurTime);
|
|
}
|
|
|
|
static void prvRtcUpdStart(void)
|
|
{
|
|
if (xRTCUpdTimer)
|
|
xTimerStart(xRTCUpdTimer, 0);
|
|
}
|
|
|
|
static void prvRtcUpdStop(void)
|
|
{
|
|
if (xRTCUpdTimer)
|
|
xTimerStop(xRTCUpdTimer, 0);
|
|
}
|
|
|
|
static void prvRtcUpdInit(void)
|
|
{
|
|
xRTCUpdTimer = xTimerCreate("UpdRTCTimer", pdMS_TO_TICKS(1000), pdTRUE,
|
|
NULL, prvRtcUpdHandler);
|
|
|
|
prvRtcGet(&ulCurTime);
|
|
ulBaseTime = timere_read();
|
|
prvRtcUpdStart();
|
|
}
|
|
|
|
static void xMboxSetRtc(void *msg)
|
|
{
|
|
unsigned int val = *(uint32_t *)msg;
|
|
|
|
VRTC_DBG("[%s]: %s val=%u\n", TAG, __func__, val);
|
|
prvRtcUpdStop();
|
|
prvRtcSet(val);
|
|
ulCurTime = val;
|
|
ulBaseTime = timere_read();
|
|
prvRtcUpdStart();
|
|
}
|
|
|
|
static void xMboxGetRtc(void *msg)
|
|
{
|
|
uint32_t val = 0;
|
|
|
|
prvRtcGet(&val);
|
|
memset(msg, 0, MBOX_BUF_LEN);
|
|
*(uint32_t *)msg = val;
|
|
VRTC_DBG("[%s]: %s val=%u\n", TAG, __func__, val);
|
|
}
|
|
|
|
#ifndef CONFIG_DISABLE_RTC_WAKEUP
|
|
static TimerHandle_t xRTCAlarmTimer;
|
|
#ifdef VRTC_TIMER_CTRL
|
|
/* separate new/old alarm set method */
|
|
static int alarm_mbox_enabled;
|
|
#endif
|
|
|
|
void vRtcAlarmSet(void)
|
|
{
|
|
uint32_t val = 0;
|
|
|
|
if (xRTCAlarmTimer) {
|
|
if (xTimerIsTimerActive(xRTCAlarmTimer)) {
|
|
val = (xTimerGetExpiryTime(xRTCAlarmTimer) - xTaskGetTickCount()) /
|
|
configTICK_RATE_HZ;
|
|
} else {
|
|
val = REG32(VRTC_PARA_REG);
|
|
if (val) {
|
|
if (val > RTC_ALARM_MAX) {
|
|
printf("[%s]: alarm %u exceeds max\n", TAG, val);
|
|
val = RTC_ALARM_MAX;
|
|
}
|
|
xTimerChangePeriod(xRTCAlarmTimer,
|
|
pdMS_TO_TICKS((uint64_t)val * 1000), 0);
|
|
}
|
|
}
|
|
if (val)
|
|
printf("[%s]: alarm val=%d S\n", TAG, val);
|
|
}
|
|
}
|
|
|
|
void vRtcAlarmClr(void)
|
|
{
|
|
if (xRTCAlarmTimer && xTimerIsTimerActive(xRTCAlarmTimer))
|
|
xTimerStop(xRTCAlarmTimer, 0);
|
|
}
|
|
|
|
static void prvRtcAlarmHandler(TimerHandle_t xTimer)
|
|
{
|
|
uint32_t buf[4] = {0};
|
|
#ifdef VRTC_TIMER_CTRL
|
|
uint32_t reg = 0;
|
|
#endif
|
|
|
|
(void)xTimer;
|
|
|
|
REG32(VRTC_PARA_REG) = 0;
|
|
if (get_suspend_flag()) {
|
|
buf[0] = RTC_WAKEUP;
|
|
printf("[%s]: vrtc alarm fired\n", TAG);
|
|
STR_Wakeup_src_Queue_Send(buf);
|
|
}
|
|
#ifdef VRTC_TIMER_CTRL
|
|
if (alarm_mbox_enabled) {
|
|
/* set timer threshold parm */
|
|
reg = FIELD_PREP(VRTC_TIMER_THRESHOLD_MASK, VRTC_TIMER_THRESHOLD_COUNT);
|
|
REG32(VRTC_TIMER) = reg;
|
|
/* enable timer(vrtc used) */
|
|
REG32(VRTC_TIMER_CTRL) |= VRTC_TIMER_ENABLE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void vRtcAlarmInit(void)
|
|
{
|
|
xRTCAlarmTimer = xTimerCreate("Timer", pdMS_TO_TICKS(1000), pdFALSE,
|
|
NULL, prvRtcAlarmHandler);
|
|
}
|
|
|
|
#ifdef VRTC_TIMER_CTRL
|
|
static void xMboxEnableRtcAlarm(void *msg)
|
|
{
|
|
uint32_t val = *(uint32_t *)msg;
|
|
uint32_t alarm;
|
|
|
|
VRTC_DBG("[%s]: %s val=%u\n", TAG, __func__, val);
|
|
if (xRTCAlarmTimer) {
|
|
if (val) {
|
|
alarm = REG32(VRTC_PARA_REG);
|
|
if (alarm) {
|
|
if (alarm > RTC_ALARM_MAX) {
|
|
printf("[%s]: alarm %u exceeds max\n", TAG, alarm);
|
|
alarm = RTC_ALARM_MAX;
|
|
}
|
|
xTimerChangePeriod(xRTCAlarmTimer,
|
|
pdMS_TO_TICKS((uint64_t)alarm * 1000), 0);
|
|
alarm_mbox_enabled = 1;
|
|
}
|
|
} else {
|
|
/* disable timer(vrtc used) */
|
|
REG32(VRTC_TIMER_CTRL) &= ~VRTC_TIMER_ENABLE;
|
|
if (xTimerIsTimerActive(xRTCAlarmTimer))
|
|
xTimerStop(xRTCAlarmTimer, 0);
|
|
alarm_mbox_enabled = 0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
void vRtcInit(void)
|
|
{
|
|
#ifdef VRTC_TIMER_CTRL
|
|
u32 reg = 0;
|
|
#endif
|
|
|
|
VRTC_DBG("[%s]: init vrtc\n", TAG);
|
|
|
|
xInstallRemoteMessageCallbackFeedBack(REE2AO_CHANNEL,
|
|
MBX_CMD_SET_RTC, (void *)xMboxSetRtc, 0);
|
|
xInstallRemoteMessageCallbackFeedBack(REE2AO_CHANNEL,
|
|
MBX_CMD_GET_RTC, (void *)xMboxGetRtc, 1);
|
|
#ifndef CONFIG_DISABLE_RTC_WAKEUP
|
|
#ifdef VRTC_TIMER_CTRL
|
|
/* enable vrtc alarm mbox callback */
|
|
xInstallRemoteMessageCallbackFeedBack(REE2AO_CHANNEL,
|
|
MBX_CMD_RTC_ENABLE_ALARM, (void *)xMboxEnableRtcAlarm, 0);
|
|
|
|
/* config timerd param */
|
|
reg = REG32(VRTC_TIMER_CTRL);
|
|
reg |= (FIELD_PREP(VRTC_TIMER_CLK_SEL, VRTC_TIMER_CLK_1US) |
|
|
FIELD_PREP(VRTC_TIMER_MODE, VRTC_TIMER_MODE_ONESHOT));
|
|
reg &= ~VRTC_TIMER_ENABLE;
|
|
REG32(VRTC_TIMER_CTRL) = reg;
|
|
#endif
|
|
vRtcAlarmInit();
|
|
#endif
|
|
prvRtcUpdInit();
|
|
}
|