Files
NANOKVM-LicheeRV-Nano-Build…/fsbl/plat/cv181x/platform.c
916BGAI dbbad1938a fsbl: sync sg200x-dev through 5a80c12
Update the vendored FSBL from Sophgo sg200x-dev commit
426d1e7eccce84b34169e5f21de7d6e7da1804a1 to
5a80c127cf614dea7f534d5b5352886a1c720d37, incorporating 24 upstream
commits. Keep the local plat/sg200x symlink to cv181x.

Import the upstream DDR, clock, storage and boot-image changes together
with their platform support, prebuilt firmware and licensing files.
All 935 upstream files match the target revision.

Validation on LicheeRV Nano (SG2002/C906, SD, DDR3-1866 x16):
- Cross-build BL2 with the existing Xuantie GCC 10.2.0 toolchain.
- Repack FIP while preserving the installed OpenSBI and U-Boot byte
  for byte; verify headers, payload checksums, entry addresses and LZMA.
- Software reboot and power-cycle boot succeed; memtester 16M 1 passes
  all 18 checks.

Validation covers the FSBL update with existing later boot stages.
Full firmware builds, A53 and video/HID acceptance are not covered.
2026-11-06 18:34:01 +08:00

628 lines
19 KiB
C

#include <cpu.h>
#include <mmio.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include <bl_common.h>
#include <platform.h>
#include <delay_timer.h>
#include <console.h>
#include <string.h>
#include <rom_api.h>
#include "ddr_pkg_info.h"
#include <ddr_sys.h>
#include <rtc.h>
extern enum CHIP_CLK_MODE chip_clk_mode;
void panic_handler(void)
{
void *ra;
ATF_ERR = ATF_ERR_PLAT_PANIC;
ra = __builtin_return_address(0);
mmio_write_32(ATF_ERR_INFO0, ((uint64_t)ra) & 0xFFFFFFFFUL);
ERROR("ra=0x%lx\n", (uint64_t)ra);
__system_reset("panic", -1);
__builtin_unreachable();
}
void __system_reset(const char *file, unsigned int line)
{
ATF_ERR = ATF_ERR_PLAT_SYSTEM_RESET;
ERROR("RESET:%s:%d\n", file, line);
console_flush();
ATF_STATE = ATF_STATE_RESET_WAIT;
mdelay(5000);
// enable rtc wdt reset
mmio_write_32(0x050260E0, 0x0001); //enable rtc_core wathdog reset enable
mmio_write_32(0x050260C8, 0x0001); //enable rtc_core power cycle enable
// sw delay 100us
ATF_STATE = ATF_STATE_RESET_RTC_WAIT;
udelay(100);
// mmio_write_32(0x05025018,0x00FFFFFF); //Mercury rtcsys_rstn_src_sel
mmio_write_32(0x050250AC, 0x00000000); //cv181x rtcsys_rstn_src_sel
mmio_write_32(0x05025004, 0x0000AB18);
mmio_write_32(0x05025008, 0x00400040); //enable rtc_ctrl wathdog reset enable
// printf("Enable TOP_WDT\n");
// mmio_write_32(0x03010004,0x00000000); //config watch dog 2.6ms
// mmio_write_32(0x03010004,0x00000022); //config watch dog 166ms
mmio_write_32(0x03010004, 0x00000066); //config watch dog 166ms
mmio_write_32(0x0301001c, 0x00000020);
mmio_write_32(0x0301000c, 0x00000076);
mmio_write_32(0x03010000, 0x00000011);
// ROM_PWR_CYC
if (get_sw_info()->reset_type == 1) {
ATF_ERR = ATF_ERR_PLAT_SYSTEM_PWR_CYC;
// printf("Issue RTCSYS_PWR_CYC\n");
// wait pmu state to ON
while (mmio_read_32(0x050260D4) != 0x00000003) {
;
}
mmio_write_32(0x05025008, 0x00080008);
}
while (1)
;
__builtin_unreachable();
}
void reset_c906l(uintptr_t reset_address)
{
NOTICE("RSC.\n");
mmio_clrbits_32(0x3003024, 1 << 6);
mmio_setbits_32(SEC_SYS_BASE + 0x04, 1 << 13);
mmio_write_32(SEC_SYS_BASE + 0x20, reset_address);
mmio_write_32(SEC_SYS_BASE + 0x24, reset_address >> 32);
mmio_setbits_32(0x3003024, 1 << 6);
}
void setup_dl_flag(void)
{
uint32_t v = p_rom_api_get_boot_src();
switch (v) {
case BOOT_SRC_UART:
mmio_write_32(BOOT_SOURCE_FLAG_ADDR, MAGIC_NUM_UART_DL);
break;
case BOOT_SRC_SD:
mmio_write_32(BOOT_SOURCE_FLAG_ADDR, MAGIC_NUM_SD_DL);
break;
case BOOT_SRC_USB:
mmio_write_32(BOOT_SOURCE_FLAG_ADDR, MAGIC_NUM_USB_DL);
break;
default:
mmio_write_32(BOOT_SOURCE_FLAG_ADDR, v);
break;
}
}
void config_core_power(uint32_t low_period)
{
/*
* low_period = 0x42; // 0.90V
* low_period = 0x48; // 0.93V
* low_period = 0x4F; // 0.96V
* low_period = 0x58; // 1.00V
* low_period = 0x5C; // 1.02V
* low_period = 0x62; // 1.05V
* low_period = 0x62; // 1.05V
*/
mmio_write_32(PWM0_BASE + PWM_HLPERIOD0, low_period);
mmio_write_32(PWM0_BASE + PWM_PERIOD0, 0x64);
mmio_write_32(PINMUX_BASE + 0xEC, 0x0); // set pinmux for pwm0
mmio_write_32(PWM0_BASE + PWM_START, 0x1); // enable bit0:pwm0 and bit3:pwm3
mmio_write_32(PWM0_BASE + PWM_OE, 0x1); // output enable bit0:pwm0 and bit3:pwm3
mdelay(10);
}
void sys_switch_all_to_pll(void)
{
// Switch all clocks to PLL
mmio_write_32(0x03002030, 0x0); // REG_CLK_BYPASS_SEL0_REG
mmio_write_32(0x03002034, 0x0); // REG_CLK_BYPASS_SEL1_REG
NOTICE("sys_switch_all_to_pll...\n");
}
void sys_pll_od(void)
{
// OD clk setting
uint32_t value;
uint32_t byp0_value;
uint32_t pll_syn_set[] = {
614440960, // set apll synthesizer 98.304 M
610080582, // set disp synthesizer 99 M
610080582, // set cam0 synthesizer 99 M
586388132, // set cam1 synthesizer 103 M
};
uint32_t pll_csr[] = {
0x00208201, // set apll *16/2 (786.432 MHz)
0x00188101, // set disp *12/1 (1188 MHz)
// 0x00188101, // set cam0 *12/1 (1188 MHz)
0x00308201, // set cam0 *24/2 (1188 MHz)
0x00148101, // set cam1 *10/1 (1030 MHz)
};
NOTICE("PLLS/OD.\n");
// set vddc for OD clock
config_core_power(0x58); //1.00V
// store byp0 value
byp0_value = mmio_read_32(0x03002030);
// switch clock to xtal
mmio_write_32(0x03002030, 0xffffffff);
mmio_write_32(0x03002034, 0x0000003f);
//set mipipll = 900MHz
mmio_write_32(0x03002808, 0x05488101);
// set synthersizer clock
mmio_write_32(REG_PLL_G2_SSC_SYN_CTRL, 0x3F); // enable synthesizer clock enable,
// [0]: 1: MIPIMPLL(900)/1=900MHz,
// 0: MIPIMPLL(900)/2=450MHz
for (uint32_t i = 0; i < 4; i++) {
mmio_write_32(REG_APLL_SSC_SYN_SET + 0x10 * i, pll_syn_set[i]); // set pll_syn_set
value = mmio_read_32(REG_APLL_SSC_SYN_CTRL + 0x10 * i);
value |= 1; // [0]: sw update (w1t: write one toggle)
value &= ~(1 << 4); // [4]: bypass = 0
mmio_write_32(REG_APLL_SSC_SYN_CTRL + 0x10 * i, value);
mmio_write_32(REG_APLL0_CSR + 4 * i, pll_csr[i]); // set pll_csr
}
value = mmio_read_32(REG_PLL_G2_CTRL);
value = value & (~0x00011111);
mmio_write_32(REG_PLL_G2_CTRL, value); //clear all pll PD
#ifdef __riscv
// set mpll = 1050MHz
mmio_write_32(0x03002908, 0x05548101);
// set div, src_mux of clk_c906_0: [20:16]div_factor=1, [9:8]clk_src = 3 (mpll), 1050/1 = 1050MHz
mmio_write_32(0x03002130, 0x00010309);
// set div, src_mux of clk_c906_1: [20:16]div_factor=1, [9:8]clk_src = 1 (a0pll), 786.432/1 = 786.432MHz
mmio_write_32(0x03002138, 0x00010109);
#else
// set mpll = 1000MHz
mmio_write_32(0x03002908, 0x05508101);
// set div, src_mux of clk_a53: [20:16]div_factor=1, [9:8]clk_src = 3 (mpll)
mmio_write_32(0x03002040, 0x00010309);
#endif
// set tpll = 1400MHz
mmio_write_32(0x0300290C, 0x07708101);
mmio_write_32(0x03002048, 0x00030009); //clk_cpu_axi0 = FPLL(1500) / 3
mmio_write_32(0x03002054, 0x00020009); //clk_tpu = TPLL(1400) / 2 = 700MHz
mmio_write_32(0x03002064, 0x00040009); //clk_emmc = FPLL(1500) / 4 = 375MHz
mmio_write_32(0x03002088, 0x00080009); //clk_spi_nand = FPLL(1500) / 8 = 187.5MHz
mmio_write_32(0x03002098, 0x00200009); //clk_sdma_aud0 = APLL(786.432) / 32 = 24.576MHz
mmio_write_32(0x03002120, 0x000F0009); //clk_pwm_src = FPLL(1500) / 15 = 100MHz
mmio_write_32(0x030020A8, 0x00010009); //clk_uart -> clk_cam0_200 = XTAL(25) / 1 = 25MHz
mmio_write_32(0x030020E4, 0x00020109); //clk_axi_video_codec = MIPIMPLL(900) / 2 = 450MHz
mmio_write_32(0x030020EC, 0x00020209); //clk_vc_src0 = CAM1PLL(1030) / 2 = 515MHz
mmio_write_32(0x030020C8, 0x00030009); //clk_axi_vip = MIPIPLL(900) / 3 = 300MHz
mmio_write_32(0x030020D0, 0x00060309); //clk_src_vip_sys_0 = FPLL(1500) / 6 = 250MHz
mmio_write_32(0x030020D8, 0x00030209); //clk_src_vip_sys_1 = DISPPLL(1188)/ 3 = 396MHz
mmio_write_32(0x03002110, 0x00020209); //clk_src_vip_sys_2 = DISPPLL(1188) / 2 = 594MHz
mmio_write_32(0x03002140, 0x00020009); //clk_src_vip_sys_3 = MIPIPLL(900) / 2 = 450MHz
mmio_write_32(0x03002144, 0x00030209); //clk_src_vip_sys_4 = DISPPLL(1188) / 3 = 396MHz
// set hsperi clock to PLL (FPLL) div by 5 = 300MHz
mmio_write_32(0x030020B8, 0x00050009); //--> CLK_AXI4
// set rtcsys clock to PLL (FPLL) div by 5 = 300MHz
mmio_write_32(0x0300212C, 0x00050009); // CLK_SRC_RTC_SYS_0
// disable powerdown, mipimpll_d3_pd[2] = 0
mmio_clrbits_32(0x030028A0, 0x4);
// disable powerdown, cam0pll_d2_pd[1]/cam0pll_d3_pd[2] = 0
mmio_clrbits_32(0x030028AC, 0x6);
//wait for pll stable
udelay(200);
#ifdef __riscv
// set clk_sel_23: [23] clk_sel for clk_c906_0 = 1 (DIV_IN0_SRC_MUX)
// set clk_sel_24: [24] clk_sel for clk_c906_1 = 1 (DIV_IN0_SRC_MUX)
mmio_write_32(0x03002020, 0x01800000);
#else
// set clk_sel_0: [0] clk_sel for clk_a53 = 1 (DIV_IN0_SRC_MUX)
// set clk_sel_24: [24] clk_sel for clk_c906_1 = 1 (DIV_IN0_SRC_MUX)
mmio_write_32(0x03002020, 0x01000001);
#endif
// switch clock to PLL from xtal except clk_axi4 & clk_spi_nand
byp0_value &= (1 << 8 | //clk_spi_nand
1 << 19 //clk_axi4
);
mmio_write_32(0x03002030, byp0_value); // REG_CLK_BYPASS_SEL0_REG
mmio_write_32(0x03002034, 0x0); // REG_CLK_BYPASS_SEL1_REG
}
void sys_pll_nd(int vc_overdrive)
{
// ND clk setting
uint32_t value;
uint32_t byp0_value;
uint32_t pll_syn_set[] = {
614440960, // set apll synthesizer 98.304 M
610080582, // set disp synthesizer 99 M
610080582, // set cam0 synthesizer 99 M
615164587, // set cam1 synthesizer 98.18181818 M
};
uint32_t pll_csr[] = {
0x00128201, // set apll *9/2 (442.368 MHz)
0x00188101, // set disp *12/1 (1188 MHz)
// 0x00188101, // set cam0 *12/1 (1188 MHz)
0x00308201, // set cam0 *24/2 (1188 MHz)
0x00168101, // set cam1 *11/1 (1080 MHz)
};
NOTICE("PLLS.\n");
if (vc_overdrive) {
pll_syn_set[3] = 586388132;
pll_csr[3] = 0x00148101;
// set vddc for OD clock
config_core_power(0x58); //1.00V
} else {
#ifdef TPU_PERF_MODE
config_core_power(0x4F);
#endif
}
// store byp0 value
byp0_value = mmio_read_32(0x03002030);
// switch clock to xtal
mmio_write_32(0x03002030, 0xffffffff);
mmio_write_32(0x03002034, 0x0000003f);
//set mipipll = 900MHz
mmio_write_32(0x03002808, 0x05488101);
// set synthersizer clock
mmio_write_32(REG_PLL_G2_SSC_SYN_CTRL, 0x3F); // enable synthesizer clock enable,
// [0]: 1: MIPIMPLL(900)/1=900MHz,
// 0: MIPIMPLL(900)/2=450MHz
for (uint32_t i = 0; i < 4; i++) {
mmio_write_32(REG_APLL_SSC_SYN_SET + 0x10 * i, pll_syn_set[i]); // set pll_syn_set
value = mmio_read_32(REG_APLL_SSC_SYN_CTRL + 0x10 * i);
value |= 1; // [0]: sw update (w1t: write one toggle)
value &= ~(1 << 4); // [4]: bypass = 0
mmio_write_32(REG_APLL_SSC_SYN_CTRL + 0x10 * i, value);
mmio_write_32(REG_APLL0_CSR + 4 * i, pll_csr[i]); // set pll_csr
}
value = mmio_read_32(REG_PLL_G2_CTRL);
value = value & (~0x00011111);
mmio_write_32(REG_PLL_G2_CTRL, value); //clear all pll PD
#ifdef __riscv
// set mpll = 850MHz
mmio_write_32(0x03002908, 0x00448101);
// set div, src_mux of clk_c906_0: [20:16]div_factor=1, [9:8]clk_src = 3 (mpll), 850/1 = 850MHz
mmio_write_32(0x03002130, 0x00010309);
// set div, src_mux of clk_c906_1: [20:16]div_factor=2, [9:8]clk_src = 2 (disppll), 1188/2 = 594MHz
mmio_write_32(0x03002138, 0x00020209);
#else
// set mpll = 800MHz
mmio_write_32(0x03002908, 0x00408101);
// set div, src_mux of clk_a53: [20:16]div_factor=1, [9:8]clk_src = 3 (mpll)
mmio_write_32(0x03002040, 0x00010309);
#endif
#ifdef TPU_PERF_MODE
// set tpll = 1400MHz
mmio_write_32(0x0300290C, 0x07708101);
mmio_write_32(0x03002054, 0x00020009); //clk_tpu = TPLL(1400) / 2 = 700MHz
#else
// set tpll = 850MHz
mmio_write_32(0x0300290C, 0x00448101);
mmio_write_32(0x03002054, 0x00030309); //clk_tpu = FPLL(1500) / 3 = 500MHz
#endif
mmio_write_32(0x03002048, 0x00030009); //clk_cpu_axi0 = FPLL(1500) / 3
mmio_write_32(0x03002064, 0x00040009); //clk_emmc = FPLL(1500) / 4 = 375MHz
mmio_write_32(0x03002088, 0x00080009); //clk_spi_nand = FPLL(1500) / 8 = 187.5MHz
mmio_write_32(0x03002098, 0x00120009); //clk_sdma_aud0 = APLL(442.368) / 18 = 24.576MHz
mmio_write_32(0x03002120, 0x000F0009); //clk_pwm_src = FPLL(1500) / 15 = 100MHz
mmio_write_32(0x030020A8, 0x00010009); //clk_uart -> clk_cam0_200 = XTAL(25) / 1 = 25MHz
mmio_write_32(0x030020C8, 0x00030009); //clk_axi_vip = MIPIPLL(900) / 3 = 300MHz
mmio_write_32(0x03002110, 0x00020209); //clk_src_vip_sys_2 = DISPPLL(1188) / 2 = 594MHz
mmio_write_32(0x03002144, 0x00030209); //clk_src_vip_sys_4 = DISPPLL(1188) / 3 = 396MHz
if (vc_overdrive) {
mmio_write_32(0x030020E4, 0x00020109); //clk_axi_video_codec = MIPIMPLL(900) / 2 = 450MHz
mmio_write_32(0x030020EC, 0x00020209); //clk_vc_src0 = CAM1PLL(1030) / 2 = 515MHz
mmio_write_32(0x030020D0, 0x00060309); //clk_src_vip_sys_0 = FPLL(1500) / 6 = 250MHz
mmio_write_32(0x030020D8, 0x00030209); //clk_src_vip_sys_1 = DISPPLL(1188)/ 3 = 396MHz
mmio_write_32(0x03002140, 0x00020009); //clk_src_vip_sys_3 = MIPIPLL(900) / 2 = 450MHz
} else {
mmio_write_32(0x030020E4, 0x00030209); //clk_axi_video_codec = CAM1PLL(1080) / 3 = 360MHz
mmio_write_32(0x030020EC, 0x00030009); //clk_vc_src0 = DISPPLL(1188) / 3 = 396MHz
mmio_write_32(0x030020D0, 0x00060209); //clk_src_vip_sys_0 = DISPPLL(1188) / 6 = 198MHz
mmio_write_32(0x030020D8, 0x00030009); //clk_src_vip_sys_1 = MIPIPLL(900) / 3 = 300MHz
mmio_write_32(0x03002140, 0x00030009); //clk_src_vip_sys_3 = MIPIPLL(900) / 3 = 300MHz
}
// set hsperi clock to PLL (FPLL) div by 5 = 300MHz
mmio_write_32(0x030020B8, 0x00050009); //--> CLK_AXI4
// set rtcsys clock to PLL (FPLL) div by 5 = 300MHz
mmio_write_32(0x0300212C, 0x00050009); // CLK_SRC_RTC_SYS_0
// disable powerdown, mipimpll_d3_pd[2] = 0
mmio_clrbits_32(0x030028A0, 0x4);
// disable powerdown, cam0pll_d2_pd[1]/cam0pll_d3_pd[2] = 0
mmio_clrbits_32(0x030028AC, 0x6);
//wait for pll stable
udelay(200);
#ifdef __riscv
// set clk_sel_23: [23] clk_sel for clk_c906_0 = 1 (DIV_IN0_SRC_MUX)
// set clk_sel_24: [24] clk_sel for clk_c906_1 = 1 (DIV_IN0_SRC_MUX)
mmio_write_32(0x03002020, 0x01800000);
#else
// set clk_sel_0: [0] clk_sel for clk_a53 = 1 (DIV_IN0_SRC_MUX)
// set clk_sel_24: [24] clk_sel for clk_c906_1 = 1 (DIV_IN0_SRC_MUX)
mmio_write_32(0x03002020, 0x01000001);
#endif
// switch clock to PLL from xtal except clk_axi4 & clk_spi_nand
byp0_value &= (1 << 8 | //clk_spi_nand
1 << 19 //clk_axi4
);
mmio_write_32(0x03002030, byp0_value); // REG_CLK_BYPASS_SEL0_REG
mmio_write_32(0x03002034, 0x0); // REG_CLK_BYPASS_SEL1_REG
NOTICE("PLLE.\n");
}
void sys_pll_init(void)
{
switch (chip_clk_mode) {
case CLK_VC_OD:
sys_pll_nd(1);
break;
case CLK_OD:
sys_pll_od();
break;
case CLK_ND:
default:
sys_pll_nd(0);
break;
}
}
#ifndef NO_DDR_CFG //for fpga
static void *get_warmboot_entry(void)
{
/*
* "FSM state change to ST_ON from the state
* 4'h0 = state changed from ST_OFF to ST_ON
* 4'h3 = state changed to ST_PWR_CYC or ST_WARM_RESET then back to ST_ON
* 4'h9 = state changed from ST_SUSP to ST_ON
*/
#define WANTED_STATE SYS_RESUME
NOTICE("\nREG_RTC_ST_ON_REASON=0x%x\n", mmio_read_32(REG_RTC_ST_ON_REASON));
NOTICE("\nRTC_SRAM_FLAG_ADDR%x=0x%x\n", RTC_SRAM_FLAG_ADDR, mmio_read_32(RTC_SRAM_FLAG_ADDR));
/* Check if RTC state changed from ST_SUSP */
if ((mmio_read_32(REG_RTC_ST_ON_REASON) & 0xF) == WANTED_STATE)
return (void *)(uintptr_t)mmio_read_32(RTC_SRAM_FLAG_ADDR);
return 0;
}
#endif
void rtc_set_ddr_pwrok(void)
{
mmio_setbits_32(REG_RTC_BASE + RTC_PG_REG, 0x00000001);
}
void rtc_set_rmio_pwrok(void)
{
mmio_setbits_32(REG_RTC_BASE + RTC_PG_REG, 0x00000002);
}
#ifndef NO_DDR_CFG //for fpga
static void ddr_resume(void)
{
rtc_set_ddr_pwrok();
rtc_set_rmio_pwrok();
ddr_sys_resume();
}
void jump_to_warmboot_entry(void)
{
void (*warmboot_entry)() = get_warmboot_entry();
// treat next reset as normal boot
mmio_write_64(RTC_SRAM_FLAG_ADDR, 0);
if (warmboot_entry) {
NOTICE("WE=0x%lx\n", (uintptr_t)warmboot_entry);
NOTICE("ddr resume...\n");
ddr_resume();
NOTICE("ddr resume end\n");
sys_pll_init();
sys_switch_all_to_pll();
#ifdef AARCH64
NOTICE("disable_mmu_el3 start...\n");
disable_mmu_el3();
__asm__ volatile("tlbi alle3\n");
/*DO NOT add any log after disable MMU*/
#endif
warmboot_entry();
}
}
#endif
void switch_rtc_mode_1st_stage(void)
{
uint32_t read_data;
uint32_t write_data;
uint32_t rtc_mode;
#ifdef AARCH64
void (*warmboot_entry)(void) = get_warmboot_entry();
if (warmboot_entry == (void *)BL31_WARMBOOT_ENTRY){
NOTICE("return %s %dwarmboot_entry\n",__func__,__LINE__);
return;
}
#endif
#ifdef CONFIG_SUSPEND
return;
#endif
// reg_rtc_mode = rtc_ctrl0[10]
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0);
rtc_mode = (read_data >> 10) & 0x1;
if (rtc_mode == 0x1) {
NOTICE("By pass rtc mode switch\n");
return;
}
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0_UNLOCKKEY, 0xAB18);
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0);
// reg_clk32k_cg_en = rtc_ctrl0[11] -> 0
write_data = 0x08000000 | (read_data & 0xfffff7ff);
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0, write_data);
//cg_en_out_clk_32k = rtc_ctrl_status0[25]
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0_STATUS0);
while ((read_data & 0x02000000) != 0x00)
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0_STATUS0);
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0);
//r eg_rtc_mode = rtc_ctrl0[10];
write_data = 0x04000000 | (read_data & 0xfffffbff) | (0x1 << 10);
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0, write_data);
// DA_SOC_READY = 1
mmio_write_32(RTC_MACRO_BASE + 0x8C, 0x01);
// DA_SOC_READY = 0
mmio_write_32(RTC_MACRO_BASE + 0x8C, 0x0);
udelay(200); // delay ~200us
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0);
// reg_clk32k_cg_en = rtc_ctrl0[11] -> 1
write_data = 0x0C000000 | (read_data & 0xffffffff) | (0x1 << 11);
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0, write_data); //rtc_ctrl0
NOTICE("Switch RTC mode to xtal32k\n");
}
void switch_rtc_mode_2nd_stage(void)
{
uint32_t read_data;
uint32_t write_data;
// mdelay(50);
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0_STATUS0);
if (get_pkg() == PKG_QFN || (read_data & 0x02000000) == 0x00) {
read_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0);
// reg_rtc_mode = rtc_ctrl0[10]
write_data = 0x0C000000 | (read_data & 0xfffffbff);
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0, write_data);
//DA_SOC_READY = 1
mmio_write_32(RTC_MACRO_BASE + 0x8C, 0x01);
//DA_SOC_READY = 0
mmio_write_32(RTC_MACRO_BASE + 0x8C, 0x00);
NOTICE("Use internal 32k\n");
} else
NOTICE("Switch RTC mode to xtal32k\n");
}
void set_rtc_en_registers(void)
{
uint32_t write_data;
#ifndef FSBL_FASTBOOT
uint32_t read_data;
read_data = mmio_read_32(REG_RTC_BASE + RTC_ST_ON_REASON);
NOTICE("st_on_reason=%x\n", read_data);
read_data = mmio_read_32(REG_RTC_BASE + RTC_ST_OFF_REASON);
NOTICE("st_off_reason=%x\n", read_data);
#endif
mmio_write_32(REG_RTC_BASE + RTC_EN_SHDN_REQ, 0x01);
while (mmio_read_32(REG_RTC_BASE + RTC_EN_SHDN_REQ) != 0x01)
;
mmio_write_32(REG_RTC_BASE + RTC_EN_WARM_RST_REQ, 0x01);
while (mmio_read_32(REG_RTC_BASE + RTC_EN_WARM_RST_REQ) != 0x01)
;
mmio_write_32(REG_RTC_BASE + RTC_EN_PWR_CYC_REQ, 0x01);
while (mmio_read_32(REG_RTC_BASE + RTC_EN_PWR_CYC_REQ) != 0x01)
;
mmio_write_32(REG_RTC_BASE + RTC_EN_WDT_RST_REQ, 0x01);
while (mmio_read_32(REG_RTC_BASE + RTC_EN_WDT_RST_REQ) != 0x01)
;
#ifdef CONFIG_SUSPEND
// Set rtcsys_rst_ctrl[24] = 1; bit 24 is reg_rtcsys_reset_en
mmio_write_32(REG_RTC_CTRL_BASE + RTC_POR_RST_CTRL, 0X2);
#else
mmio_write_32(REG_RTC_CTRL_BASE + RTC_POR_RST_CTRL, 0X1);
#endif
// rtc_ctrl0_unlockkey
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0_UNLOCKKEY, 0xAB18);
// Enable hw_wdg_rst_en
write_data = mmio_read_32(REG_RTC_CTRL_BASE + RTC_CTRL0);
write_data = 0xffff0000 | write_data | (0x1 << 11) | (0x01 << 6);
mmio_write_32(REG_RTC_CTRL_BASE + RTC_CTRL0, write_data);
// Avoid power up again after poweroff
mmio_clrbits_32(REG_RTC_BASE + RTC_EN_PWR_VBAT_DET, BIT(2));
}
void apply_analog_trimming_data(void)
{
}