blob: a4da1ed520e707cc74d246500384e7a2c19abf1f [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"
Xiaohu.Huang60950452022-03-12 22:51:01 +080020
21#undef TAG
22#define TAG "AOCPU RTC"
23
yiting.deng21d1aa42023-02-08 17:46:11 +080024static uint32_t gray_to_binary(uint32_t gray)
25{
26 uint32_t bcd = gray;
27 int size = sizeof(bcd) * 8;
28 int i;
29
30 for (i = 0; (1 << i) < size; i++)
31 bcd ^= bcd >> (1 << i);
32
33 return bcd;
34}
35
Xiaohu.Huang60950452022-03-12 22:51:01 +080036static void vRTCInterruptHandler(void)
37{
xiaohu.huang2beac512022-05-07 15:10:04 +080038 uint32_t buf[4] = { 0 };
Xiaohu.Huang60950452022-03-12 22:51:01 +080039 uint32_t alarm0_int_status;
40 uint32_t reg_val;
41
42 /* Mask alarm0 irq */
yiting.deng21d1aa42023-02-08 17:46:11 +080043 reg_val = REG32(RTC_DIG_INT_MASK);
Xiaohu.Huang60950452022-03-12 22:51:01 +080044 reg_val |= 0x1;
yiting.deng21d1aa42023-02-08 17:46:11 +080045 REG32(RTC_DIG_INT_MASK) = reg_val;
Xiaohu.Huang60950452022-03-12 22:51:01 +080046
47 /* Clear alarm0 */
yiting.deng21d1aa42023-02-08 17:46:11 +080048 REG32(RTC_DIG_ALARM0_REG) = 0;
Xiaohu.Huang60950452022-03-12 22:51:01 +080049
yiting.deng21d1aa42023-02-08 17:46:11 +080050 alarm0_int_status = REG32(RTC_DIG_INT_STATUS) & (1 << RTC_INT_ALM0_IRQ);
Xiaohu.Huang60950452022-03-12 22:51:01 +080051 /* Clear alarm0 int status */
52 if (alarm0_int_status)
yiting.deng21d1aa42023-02-08 17:46:11 +080053 REG32(RTC_DIG_INT_CLR) |= (1 << RTC_INT_CLR_ALM0_IRQ);
Xiaohu.Huang60950452022-03-12 22:51:01 +080054
55 printf("[%s]: rtc alarm fired\n", TAG);
56
57 buf[0] = RTC_WAKEUP;
58 STR_Wakeup_src_Queue_Send_FromISR(buf);
59}
60
61static uint32_t get_reboot_mode(void)
62{
63 uint32_t reg_val;
64 uint32_t reboot_mode;
65
66 reg_val = REG32(SYSCTRL_SEC_STATUS_REG31);
67 reboot_mode = ((reg_val >> 12) & 0xf);
68
69 return reboot_mode;
70}
71
72static void reset_rtc(void)
73{
74 uint32_t reg_val;
75
76 printf("[%s]: reset rtc\n", TAG);
77 /* Reset RTC */
78 reg_val = (1 << 0);
79 REG32(RESETCTRL_RESET4) = reg_val;
80 /* Mask RTC reset to prevent RTC being reset in the next reboot */
81 reg_val = REG32(RESETCTRL_RESET4_MASK);
82 reg_val |= (1 << 0);
83 REG32(RESETCTRL_RESET4_MASK) = reg_val;
84}
85
86static int get_rtc(uint32_t *val)
87{
88 if (!REG32(VRTC_STICKY_REG))
89 return -1;
Xiaohu.Huang60950452022-03-12 22:51:01 +080090
xiaohu.huang2beac512022-05-07 15:10:04 +080091 *(val) = REG32(VRTC_STICKY_REG);
Xiaohu.Huang60950452022-03-12 22:51:01 +080092 return 0;
93}
94
95static void set_rtc(uint32_t val)
96{
97 REG32(VRTC_STICKY_REG) = val;
98}
99
100void store_rtc(void)
101{
102 uint32_t reg_val;
103
yiting.deng21d1aa42023-02-08 17:46:11 +0800104 reg_val = REG32(RTC_DIG_REAL_TIME);
105#ifdef CONFIG_RTC_STORAGE_FORMAT_GRAY
106 reg_val = gray_to_binary(reg_val);
107#endif
Xiaohu.Huang60950452022-03-12 22:51:01 +0800108 REG32(VRTC_STICKY_REG) = reg_val;
109}
110
111void *MboxSetRTC(void *msg)
112{
113 unsigned int val = *(uint32_t *)msg;
xiaohu.huang2beac512022-05-07 15:10:04 +0800114
115 printf("[%s]: %s val=0x%x\n", TAG, __func__, val);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800116 set_rtc(val);
117
118 return NULL;
119}
120
121void *MboxGetRTC(void *msg)
122{
123 uint32_t val = 0;
124
125 get_rtc(&val);
126 memset(msg, 0, MBOX_BUF_LEN);
127 *(uint32_t *)msg = val;
128
xiaohu.huang2beac512022-05-07 15:10:04 +0800129 printf("[%s]: %s val=0x%x\n", TAG, __func__, val);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800130
131 return NULL;
132}
133
134void rtc_init(void)
135{
136 int ret;
137 uint32_t reboot_mode;
138
139 printf("[%s]: init rtc\n", TAG);
140 ret = RegisterIrq(RTC_IRQ, 6, vRTCInterruptHandler);
141 if (ret)
142 printf("[%s]: RegisterIrq error, ret = %d\n", TAG, ret);
143 EnableIrq(RTC_IRQ);
144
xiaohu.huang2beac512022-05-07 15:10:04 +0800145 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_SET_RTC, MboxSetRTC, 0);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800146 if (ret == MBOX_CALL_MAX)
147 printf("[%s]: mbox cmd 0x%x register fail\n", TAG, MBX_CMD_SET_RTC);
148
xiaohu.huang2beac512022-05-07 15:10:04 +0800149 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_RTC, MboxGetRTC, 1);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800150 if (ret == MBOX_CALL_MAX)
151 printf("[%s]: mbox cmd 0x%x register fail\n", TAG, MBX_CMD_GET_RTC);
152
153 reboot_mode = get_reboot_mode();
154 if (reboot_mode == COLD_REBOOT)
155 reset_rtc();
156}