122 lines
2.8 KiB
C
122 lines
2.8 KiB
C
/*
|
|
*
|
|
* (C) Copyright 2019
|
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
|
* frank <frank@allwinnertech.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <errno.h>
|
|
#include <asm/io.h>
|
|
#include <arch/rtc.h>
|
|
#include <arch/watchdog.h>
|
|
#include <arch/clock.h>
|
|
|
|
#define DRAM_CRC_MAGIC (0x76543210)
|
|
|
|
typedef struct pm_dram_para {
|
|
unsigned int selfresh_flag;
|
|
unsigned int crc_en;
|
|
unsigned int crc_start;
|
|
unsigned int crc_len;
|
|
} pm_dram_para_t;
|
|
|
|
static pm_dram_para_t soc_dram_state;
|
|
static u32 before_crc;
|
|
static u32 after_crc;
|
|
|
|
static u32 standby_dram_crc_enable(pm_dram_para_t *pdram_state)
|
|
{
|
|
return pdram_state->crc_en;
|
|
}
|
|
|
|
static u32 standby_dram_crc(pm_dram_para_t *pdram_state)
|
|
{
|
|
u32 *pdata;
|
|
u32 crc = 0;
|
|
|
|
pdata = (u32 *)(pdram_state->crc_start);
|
|
printf("src:0x%x\n", (unsigned int)pdata);
|
|
printf("len addr = 0x%x, len:0x%x\n",
|
|
(unsigned int) (&(pdram_state->crc_len)),
|
|
pdram_state->crc_len);
|
|
while (pdata < (u32 *)(pdram_state->crc_start +
|
|
pdram_state->crc_len)) {
|
|
crc += *pdata;
|
|
pdata++;
|
|
}
|
|
printf("crc finish...\n");
|
|
return crc;
|
|
}
|
|
|
|
static int probe_super_standby_flag(void)
|
|
{
|
|
uint reg_value = 0;
|
|
int standby_flag = 0;
|
|
|
|
reg_value = readl(RTC_STANDBY_FLAG_REG);
|
|
standby_flag = (reg_value & ~(0xfffe0000)) >> 16;
|
|
printf("rtc standby flag is 0x%x, super standby flag is 0x%x\n",
|
|
reg_value, standby_flag);
|
|
writel(0, RTC_STANDBY_FLAG_REG);
|
|
|
|
return standby_flag;
|
|
}
|
|
|
|
int super_standby_mode(void)
|
|
{
|
|
uint reg_value = 0;
|
|
int standby_flag = 0;
|
|
|
|
reg_value = readl(RTC_STANDBY_FLAG_REG);
|
|
standby_flag = (reg_value & ~(0xfffe0000)) >> 16;
|
|
|
|
return standby_flag;
|
|
}
|
|
|
|
void handler_super_standby(void)
|
|
{
|
|
if (probe_super_standby_flag()) {
|
|
|
|
/* high 28 bits for magic number, low 4 bits for enable */
|
|
if ((rtc_read_data(CRC_EN) & (~0xf)) == DRAM_CRC_MAGIC) {
|
|
soc_dram_state.crc_en = rtc_read_data(CRC_EN) & 0xf;
|
|
soc_dram_state.crc_start = rtc_read_data(CRC_START);
|
|
soc_dram_state.crc_len = rtc_read_data(CRC_LEN);
|
|
}
|
|
|
|
if (standby_dram_crc_enable(&soc_dram_state)) {
|
|
before_crc = rtc_read_data(CRC_VALUE_BEFORE);
|
|
after_crc = standby_dram_crc(&soc_dram_state);
|
|
printf("before_crc = 0x%x, after_crc = 0x%x\n",
|
|
before_crc, after_crc);
|
|
if (before_crc != after_crc) {
|
|
printf("dram crc error ...\n");
|
|
wdt_start(0);
|
|
asm ("b .");
|
|
}
|
|
}
|
|
/*
|
|
* /dram_enable_all_master(); Not implemented on fpga
|
|
*/
|
|
printf("find standby flag, jump to addr 0x%x\n",
|
|
readl(RTC_STANDBY_SOFT_ENTRY_REG));
|
|
/* FIX ME: need 500ms ?
|
|
*__msdelay(500);
|
|
*/
|
|
#ifdef CFG_SUNXI_SBOOT
|
|
int sunxi_smc_resume(int secure_entry);
|
|
/* Borrowing the standby jmp address
|
|
* to calculate the address of monitor or optee
|
|
*/
|
|
sunxi_smc_resume(readl(RTC_STANDBY_SOFT_ENTRY_REG) & 0xfff00000);
|
|
#endif
|
|
udelay(20);
|
|
#ifdef CONFIG_MONITOR
|
|
boot0_jmp_monitor(readl(RTC_STANDBY_SOFT_ENTRY_REG));
|
|
#else
|
|
boot0_jmp(readl(RTC_STANDBY_SOFT_ENTRY_REG));
|
|
#endif
|
|
}
|
|
}
|