blob: 13f7bc33460d1bfe52b5ed62bcc5637160ed4073 [file] [log] [blame]
Xiaohu.Huang60950452022-03-12 22:51:01 +08001/*
2 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include <stdio.h>
8#include <string.h>
9#include <unistd.h>
10#include "common.h"
11#include "rtc.h"
12#include "register.h"
13#include "FreeRTOS.h"
14#include "mailbox-api.h"
15#include "soc.h"
16#include "string.h"
17#include "interrupt.h"
18#include "suspend.h"
yiting.deng21d1aa42023-02-08 17:46:11 +080019#include "rtc_register.h"
yiting.dengac5b18d2023-04-25 11:13:26 +080020#include "timers.h"
21#include "interrupt_control_eclic.h"
Xiaohu.Huang60950452022-03-12 22:51:01 +080022
23#undef TAG
24#define TAG "AOCPU RTC"
25
yiting.dengac5b18d2023-04-25 11:13:26 +080026static TimerHandle_t xAlarmTimer;
27static int alarm_flags;
28
yiting.deng21d1aa42023-02-08 17:46:11 +080029static uint32_t gray_to_binary(uint32_t gray)
30{
31 uint32_t bcd = gray;
32 int size = sizeof(bcd) * 8;
33 int i;
34
35 for (i = 0; (1 << i) < size; i++)
36 bcd ^= bcd >> (1 << i);
37
38 return bcd;
39}
40
Xiaohu.Huang60950452022-03-12 22:51:01 +080041static void vRTCInterruptHandler(void)
42{
xiaohu.huang2beac512022-05-07 15:10:04 +080043 uint32_t buf[4] = { 0 };
Xiaohu.Huang60950452022-03-12 22:51:01 +080044
yiting.dengac5b18d2023-04-25 11:13:26 +080045 alarm_flags = 1;
Xiaohu.Huang60950452022-03-12 22:51:01 +080046 printf("[%s]: rtc alarm fired\n", TAG);
47
48 buf[0] = RTC_WAKEUP;
49 STR_Wakeup_src_Queue_Send_FromISR(buf);
50}
51
52static uint32_t get_reboot_mode(void)
53{
54 uint32_t reg_val;
55 uint32_t reboot_mode;
56
57 reg_val = REG32(SYSCTRL_SEC_STATUS_REG31);
58 reboot_mode = ((reg_val >> 12) & 0xf);
59
60 return reboot_mode;
61}
62
63static void reset_rtc(void)
64{
65 uint32_t reg_val;
66
67 printf("[%s]: reset rtc\n", TAG);
68 /* Reset RTC */
69 reg_val = (1 << 0);
70 REG32(RESETCTRL_RESET4) = reg_val;
71 /* Mask RTC reset to prevent RTC being reset in the next reboot */
72 reg_val = REG32(RESETCTRL_RESET4_MASK);
73 reg_val |= (1 << 0);
74 REG32(RESETCTRL_RESET4_MASK) = reg_val;
75}
76
77static int get_rtc(uint32_t *val)
78{
79 if (!REG32(VRTC_STICKY_REG))
80 return -1;
Xiaohu.Huang60950452022-03-12 22:51:01 +080081
xiaohu.huang2beac512022-05-07 15:10:04 +080082 *(val) = REG32(VRTC_STICKY_REG);
Xiaohu.Huang60950452022-03-12 22:51:01 +080083 return 0;
84}
85
86static void set_rtc(uint32_t val)
87{
88 REG32(VRTC_STICKY_REG) = val;
89}
90
91void store_rtc(void)
92{
93 uint32_t reg_val;
94
yiting.deng21d1aa42023-02-08 17:46:11 +080095 reg_val = REG32(RTC_DIG_REAL_TIME);
96#ifdef CONFIG_RTC_STORAGE_FORMAT_GRAY
97 reg_val = gray_to_binary(reg_val);
98#endif
Xiaohu.Huang60950452022-03-12 22:51:01 +080099 REG32(VRTC_STICKY_REG) = reg_val;
100}
101
102void *MboxSetRTC(void *msg)
103{
104 unsigned int val = *(uint32_t *)msg;
xiaohu.huang2beac512022-05-07 15:10:04 +0800105
106 printf("[%s]: %s val=0x%x\n", TAG, __func__, val);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800107 set_rtc(val);
108
109 return NULL;
110}
111
112void *MboxGetRTC(void *msg)
113{
114 uint32_t val = 0;
115
116 get_rtc(&val);
117 memset(msg, 0, MBOX_BUF_LEN);
118 *(uint32_t *)msg = val;
119
xiaohu.huang2beac512022-05-07 15:10:04 +0800120 printf("[%s]: %s val=0x%x\n", TAG, __func__, val);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800121
122 return NULL;
123}
124
yiting.deng6ec1d642023-03-19 10:10:35 +0800125void rtc_enable_irq(void)
126{
yiting.dengbfc3f452023-05-18 16:22:40 +0800127 int ret, val;
yiting.dengac5b18d2023-04-25 11:13:26 +0800128 u32 alarm, time;
yiting.deng6ec1d642023-03-19 10:10:35 +0800129
yiting.dengac5b18d2023-04-25 11:13:26 +0800130 alarm = REG32(RTC_DIG_ALARM0_REG);
yiting.dengbfc3f452023-05-18 16:22:40 +0800131 time = REG32(RTC_DIG_REAL_TIME);
132#ifdef CONFIG_RTC_STORAGE_FORMAT_GRAY
133 alarm = gray_to_binary(alarm);
134 time = gray_to_binary(time);
135#endif
136 val = alarm - time;
137 if (val > 0) {
yiting.dengac5b18d2023-04-25 11:13:26 +0800138 ret = RegisterIrq(RTC_IRQ, 6, vRTCInterruptHandler);
139 if (ret)
140 printf("RTC_irq RegisterIrq error, ret = %d\n", ret);
141 EnableIrq(RTC_IRQ);
yiting.dengbfc3f452023-05-18 16:22:40 +0800142 printf("[%s]: alarm val=%d S\n", TAG, val);
143 if (xAlarmTimer != NULL) {
144 alarm = (val + 1) * 1000;
yiting.dengac5b18d2023-04-25 11:13:26 +0800145 xTimerChangePeriod(xAlarmTimer, pdMS_TO_TICKS(alarm), 0);
146 }
147 }
yiting.deng6ec1d642023-03-19 10:10:35 +0800148}
149
150void rtc_disable_irq(void)
151{
yiting.dengbfc3f452023-05-18 16:22:40 +0800152 int ret, val;
yiting.deng6ec1d642023-03-19 10:10:35 +0800153
yiting.deng4c21b172023-08-29 15:44:23 +0800154 val = GetIrqInner(RTC_IRQ);
yiting.dengbfc3f452023-05-18 16:22:40 +0800155 if (val > 0) {
yiting.dengac5b18d2023-04-25 11:13:26 +0800156 DisableIrq(RTC_IRQ);
157 ret = UnRegisterIrq(RTC_IRQ);
158 if (ret)
159 printf("RTC_irq UnRegisterIrq error, ret = %d\n", ret);
160 }
161}
162
163static void rtc_alarm_timer_handler(TimerHandle_t xAlarmTimer)
164{
165 static int rtc_irq, status;
166
167 status = REG32(RTC_DIG_INT_STATUS) & 0x1;
168 if (status && !alarm_flags) {
169 rtc_irq = GetIrqInner(RTC_IRQ);
170 if (rtc_irq)
171 eclic_set_pending(rtc_irq);
172 }
173 alarm_flags = 0;
174}
175
176void alarm_clr(void)
177{
178 if (xAlarmTimer != NULL)
179 xTimerStop(xAlarmTimer, 0);
180}
181
182static void rtc_alarm_timer_init(void)
183{
184 xAlarmTimer = xTimerCreate("RtcAlarmTimer", pdMS_TO_TICKS(1000),
185 pdFALSE, NULL, rtc_alarm_timer_handler);
yiting.deng6ec1d642023-03-19 10:10:35 +0800186}
187
Xiaohu.Huang60950452022-03-12 22:51:01 +0800188void rtc_init(void)
189{
190 int ret;
191 uint32_t reboot_mode;
192
193 printf("[%s]: init rtc\n", TAG);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800194
xiaohu.huang2beac512022-05-07 15:10:04 +0800195 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_SET_RTC, MboxSetRTC, 0);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800196 if (ret == MBOX_CALL_MAX)
197 printf("[%s]: mbox cmd 0x%x register fail\n", TAG, MBX_CMD_SET_RTC);
198
xiaohu.huang2beac512022-05-07 15:10:04 +0800199 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_RTC, MboxGetRTC, 1);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800200 if (ret == MBOX_CALL_MAX)
201 printf("[%s]: mbox cmd 0x%x register fail\n", TAG, MBX_CMD_GET_RTC);
202
203 reboot_mode = get_reboot_mode();
204 if (reboot_mode == COLD_REBOOT)
205 reset_rtc();
yiting.dengac5b18d2023-04-25 11:13:26 +0800206
207 rtc_alarm_timer_init();
Xiaohu.Huang60950452022-03-12 22:51:01 +0800208}