Files
SDK_SG200x_V2/fsbl/plat/cv181x/bl2/bl2_opt.c
sophgo-forum-service 4df417855c fsbl: weekly rls 2024.07.20
-8ead06, add new feature for cv181x/cv180x suspend to ram.

Change-Id: I4b4f0fc51b9028d6d006ebcf579b0f4c19007780
2024-07-25 14:46:16 +08:00

494 lines
12 KiB
C

/*
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <bitwise_ops.h>
#include <console.h>
#include <platform.h>
#include <rom_api.h>
#include <bl2.h>
#include <ddr.h>
#include <ddr_sys.h>
#include <rtc.h>
#include <string.h>
#include <decompress.h>
#include <delay_timer.h>
#include <security/security.h>
struct _time_records *time_records = (void *)TIME_RECORDS_ADDR;
struct fip_param1 *fip_param1 = (void *)PARAM1_BASE;
enum CHIP_CLK_MODE chip_clk_mode = CLK_ND;
static struct fip_param2 fip_param2 __aligned(BLOCK_SIZE);
static union {
struct ddr_param ddr_param;
struct loader_2nd_header loader_2nd_header;
uint8_t buf[BLOCK_SIZE];
} sram_union_buf __aligned(BLOCK_SIZE);
int init_comm_info(int ret) __attribute__((weak));
int init_comm_info(int ret)
{
return ret;
}
void print_sram_log(void)
{
uint32_t *const log_size = (void *)BOOT_LOG_LEN_ADDR;
uint8_t *const log_buf = (void *)phys_to_dma(BOOT_LOG_BUF_BASE);
uint32_t i;
static const char m1[] = "\nSRAM Log: ========================================\n";
static const char m2[] = "\nSRAM Log end: ====================================\n";
for (i = 0; m1[i]; i++)
console_putc(m1[i]);
for (i = 0; i < *log_size; i++)
console_putc(log_buf[i]);
for (i = 0; m2[i]; i++)
console_putc(m2[i]);
}
void lock_efuse_chipsn(void)
{
int value = mmio_read_32(EFUSE_W_LOCK0_REG);
if (efuse_power_on()) {
NOTICE("efuse power on fail\n");
return;
}
if ((value & (0x1 << BIT_FTSN3_LOCK)) == 0)
efuse_program_bit(0x26, BIT_FTSN3_LOCK);
if ((value & (0x1 << BIT_FTSN4_LOCK)) == 0)
efuse_program_bit(0x26, BIT_FTSN4_LOCK);
if (efuse_refresh_shadow()) {
NOTICE("efuse refresh shadow fail\n");
return;
}
value = mmio_read_32(EFUSE_W_LOCK0_REG);
if (((value & (0x3 << BIT_FTSN3_LOCK)) >> BIT_FTSN3_LOCK) != 0x3)
NOTICE("lock efuse chipsn fail\n");
if (efuse_power_off()) {
NOTICE("efuse power off fail\n");
return;
}
}
int load_param2(int retry)
{
uint32_t crc;
int ret = -1;
NOTICE("P2S/0x%lx/%p.\n", sizeof(fip_param2), &fip_param2);
ret = p_rom_api_load_image(&fip_param2, fip_param1->param2_loadaddr, PARAM2_SIZE, retry);
if (ret < 0) {
return ret;
}
if (fip_param2.magic1 != FIP_PARAM2_MAGIC1) {
WARN("LP2_NOMAGIC\n");
return -1;
}
crc = p_rom_api_image_crc(&fip_param2.reserved1, sizeof(fip_param2) - 12);
if (crc != fip_param2.param2_cksum) {
ERROR("param2_cksum (0x%x/0x%x)\n", crc, fip_param2.param2_cksum);
return -1;
}
NOTICE("P2E.\n");
return 0;
}
int load_ddr_param(int retry)
{
uint32_t crc;
int ret = -1;
NOTICE("DPS/0x%x/0x%x.\n", fip_param2.ddr_param_loadaddr, fip_param2.ddr_param_size);
if (fip_param2.ddr_param_size >= sizeof(sram_union_buf.ddr_param))
fip_param2.ddr_param_size = sizeof(sram_union_buf.ddr_param);
ret = p_rom_api_load_image(&sram_union_buf.ddr_param, fip_param2.ddr_param_loadaddr, fip_param2.ddr_param_size,
retry);
if (ret < 0) {
return ret;
}
crc = p_rom_api_image_crc(&sram_union_buf.ddr_param, fip_param2.ddr_param_size);
if (crc != fip_param2.ddr_param_cksum) {
ERROR("ddr_param_cksum (0x%x/0x%x)\n", crc, fip_param2.ddr_param_cksum);
return -1;
}
NOTICE("DPE.\n");
return 0;
}
int load_ddr(void)
{
int retry = 0;
retry_from_flash:
for (retry = 0; retry < p_rom_api_get_number_of_retries(); retry++) {
if (load_param2(retry) < 0)
continue;
if (load_ddr_param(retry) < 0)
continue;
break;
}
if (retry >= p_rom_api_get_number_of_retries()) {
switch (p_rom_api_get_boot_src()) {
case BOOT_SRC_UART:
case BOOT_SRC_SD:
case BOOT_SRC_USB:
WARN("DL cancelled. Load flash. (%d).\n", retry);
// Continue to boot from flash if boot from external source
p_rom_api_flash_init();
goto retry_from_flash;
default:
ERROR("Failed to load DDR param (%d).\n", retry);
panic_handler();
}
}
time_records->ddr_init_start = read_time_ms();
ddr_init(&sram_union_buf.ddr_param);
time_records->ddr_init_end = read_time_ms();
return 0;
}
int load_blcp_2nd(int retry)
{
uint32_t crc, rtos_base;
int ret = -1;
// if no blcp_2nd, release_blcp_2nd should be ddr_init_end
time_records->release_blcp_2nd = time_records->ddr_init_end;
NOTICE("C2S/0x%x/0x%x/0x%x.\n", fip_param2.blcp_2nd_loadaddr, fip_param2.blcp_2nd_runaddr,
fip_param2.blcp_2nd_size);
if (!fip_param2.blcp_2nd_runaddr) {
NOTICE("No C906L image.\n");
return 0;
}
if (!IN_RANGE(fip_param2.blcp_2nd_runaddr, DRAM_BASE, DRAM_SIZE)) {
ERROR("blcp_2nd_runaddr (0x%x) is not in DRAM.\n", fip_param2.blcp_2nd_runaddr);
panic_handler();
}
if (!IN_RANGE(fip_param2.blcp_2nd_runaddr + fip_param2.blcp_2nd_size, DRAM_BASE, DRAM_SIZE)) {
ERROR("blcp_2nd_size (0x%x) is not in DRAM.\n", fip_param2.blcp_2nd_size);
panic_handler();
}
ret = p_rom_api_load_image((void *)(uintptr_t)fip_param2.blcp_2nd_runaddr, fip_param2.blcp_2nd_loadaddr,
fip_param2.blcp_2nd_size, retry);
if (ret < 0) {
return ret;
}
crc = p_rom_api_image_crc((void *)(uintptr_t)fip_param2.blcp_2nd_runaddr, fip_param2.blcp_2nd_size);
if (crc != fip_param2.blcp_2nd_cksum) {
ERROR("blcp_2nd_cksum (0x%x/0x%x)\n", crc, fip_param2.blcp_2nd_cksum);
return -1;
}
ret = dec_verify_image((void *)(uintptr_t)fip_param2.blcp_2nd_runaddr, fip_param2.blcp_2nd_size, 0, fip_param1);
if (ret < 0) {
ERROR("verify blcp 2nd (%d)\n", ret);
return ret;
}
flush_dcache_range(fip_param2.blcp_2nd_runaddr, fip_param2.blcp_2nd_size);
rtos_base = mmio_read_32(AXI_SRAM_RTOS_BASE);
init_comm_info(0);
time_records->release_blcp_2nd = read_time_ms();
if (rtos_base == CVI_RTOS_MAGIC_CODE) {
mmio_write_32(AXI_SRAM_RTOS_BASE, fip_param2.blcp_2nd_runaddr);
} else {
reset_c906l(fip_param2.blcp_2nd_runaddr);
}
NOTICE("C2E.\n");
return 0;
}
int load_monitor(int retry, uint64_t *monitor_entry)
{
uint32_t crc;
int ret = -1;
NOTICE("MS/0x%x/0x%x/0x%x.\n", fip_param2.monitor_loadaddr, fip_param2.monitor_runaddr,
fip_param2.monitor_size);
if (!fip_param2.monitor_runaddr) {
NOTICE("No monitor.\n");
return 0;
}
if (!IN_RANGE(fip_param2.monitor_runaddr, DRAM_BASE, DRAM_SIZE)) {
ERROR("monitor_runaddr (0x%x) is not in DRAM.\n", fip_param2.monitor_runaddr);
panic_handler();
}
if (!IN_RANGE(fip_param2.monitor_runaddr + fip_param2.monitor_size, DRAM_BASE, DRAM_SIZE)) {
ERROR("monitor_size (0x%x) is not in DRAM.\n", fip_param2.monitor_size);
panic_handler();
}
ret = p_rom_api_load_image((void *)(uintptr_t)fip_param2.monitor_runaddr, fip_param2.monitor_loadaddr,
fip_param2.monitor_size, retry);
if (ret < 0) {
return ret;
}
crc = p_rom_api_image_crc((void *)(uintptr_t)fip_param2.monitor_runaddr, fip_param2.monitor_size);
if (crc != fip_param2.monitor_cksum) {
ERROR("monitor_cksum (0x%x/0x%x)\n", crc, fip_param2.monitor_cksum);
return -1;
}
ret = dec_verify_image((void *)(uintptr_t)fip_param2.monitor_runaddr, fip_param2.monitor_size, 0, fip_param1);
if (ret < 0) {
ERROR("verify monitor (%d)\n", ret);
return ret;
}
flush_dcache_range(fip_param2.monitor_runaddr, fip_param2.monitor_size);
NOTICE("ME.\n");
*monitor_entry = fip_param2.monitor_runaddr;
return 0;
}
int load_loader_2nd(int retry, uint64_t *loader_2nd_entry)
{
struct loader_2nd_header *loader_2nd_header = &sram_union_buf.loader_2nd_header;
uint32_t crc;
int ret = -1;
const int cksum_offset =
offsetof(struct loader_2nd_header, cksum) + sizeof(((struct loader_2nd_header *)0)->cksum);
enum COMPRESS_TYPE comp_type = COMP_NONE;
int reading_size;
void *image_buf;
NOTICE("L2/0x%x.\n", fip_param2.loader_2nd_loadaddr);
ret = p_rom_api_load_image(loader_2nd_header, fip_param2.loader_2nd_loadaddr, BLOCK_SIZE, retry);
if (ret < 0) {
return -1;
}
reading_size = ROUND_UP(loader_2nd_header->size, BLOCK_SIZE);
NOTICE("L2/0x%x/0x%x/0x%lx/0x%x/0x%x\n", loader_2nd_header->magic, loader_2nd_header->cksum,
loader_2nd_header->runaddr, loader_2nd_header->size, reading_size);
switch (loader_2nd_header->magic) {
case LOADER_2ND_MAGIC_LZMA:
comp_type = COMP_LZMA;
break;
case LOADER_2ND_MAGIC_LZ4:
comp_type = COMP_LZ4;
break;
default:
comp_type = COMP_NONE;
break;
}
if (comp_type) {
NOTICE("COMP/%d.\n", comp_type);
image_buf = (void *)DECOMP_BUF_ADDR;
} else {
image_buf = (void *)loader_2nd_header->runaddr;
}
ret = p_rom_api_load_image(image_buf, fip_param2.loader_2nd_loadaddr, reading_size, retry);
if (ret < 0) {
return -1;
}
crc = p_rom_api_image_crc(image_buf + cksum_offset, loader_2nd_header->size - cksum_offset);
if (crc != loader_2nd_header->cksum) {
ERROR("loader_2nd_cksum (0x%x/0x%x)\n", crc, loader_2nd_header->cksum);
return -1;
}
ret = dec_verify_image(image_buf + cksum_offset, loader_2nd_header->size - cksum_offset,
sizeof(struct loader_2nd_header) - cksum_offset, fip_param1);
if (ret < 0) {
ERROR("verify loader 2nd (%d)\n", ret);
return ret;
}
time_records->load_loader_2nd_end = read_time_ms();
sys_switch_all_to_pll();
time_records->fsbl_decomp_start = read_time_ms();
if (comp_type) {
size_t dst_size = DECOMP_DST_SIZE;
// header is not compressed.
void *dst = (void *)loader_2nd_header->runaddr;
memcpy(dst, image_buf, sizeof(struct loader_2nd_header));
image_buf += sizeof(struct loader_2nd_header);
ret = decompress(dst + sizeof(struct loader_2nd_header), &dst_size, image_buf, loader_2nd_header->size,
comp_type);
if (ret < 0) {
ERROR("Failed to decompress loader_2nd (%d/%lu)\n", ret, dst_size);
return -1;
}
reading_size = dst_size;
}
flush_dcache_range(loader_2nd_header->runaddr, reading_size);
time_records->fsbl_decomp_end = read_time_ms();
NOTICE("Loader_2nd loaded.\n");
*loader_2nd_entry = loader_2nd_header->runaddr + sizeof(struct loader_2nd_header);
return 0;
}
#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 0x9
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(enum CHIP_CLK_MODE mode)
{
void (*warmboot_entry)() = get_warmboot_entry();
// treat next reset as normal boot
mmio_write_64(RTC_SRAM_FLAG_ADDR, 0);
if (warmboot_entry) {
INFO("WE=0x%lx\n", (uintptr_t)warmboot_entry);
NOTICE("ddr resume...\n");
ddr_resume();
NOTICE("ddr resume end\n");
sys_pll_init(mode);
sys_switch_all_to_pll();
warmboot_entry();
}
}
#endif
int load_rest(enum CHIP_CLK_MODE mode)
{
int retry = 0;
uint64_t monitor_entry = 0;
uint64_t loader_2nd_entry = 0;
// Init sys PLL and switch clocks to PLL
sys_pll_init(mode);
retry_from_flash:
for (retry = 0; retry < p_rom_api_get_number_of_retries(); retry++) {
if (load_blcp_2nd(retry) < 0)
continue;
if (load_monitor(retry, &monitor_entry) < 0)
continue;
if (load_loader_2nd(retry, &loader_2nd_entry) < 0)
continue;
break;
}
if (retry >= p_rom_api_get_number_of_retries()) {
switch (p_rom_api_get_boot_src()) {
case BOOT_SRC_UART:
case BOOT_SRC_SD:
case BOOT_SRC_USB:
WARN("DL cancelled. Load flash. (%d).\n", retry);
// Continue to boot from flash if boot from external source
p_rom_api_flash_init();
goto retry_from_flash;
default:
ERROR("Failed to load rest (%d).\n", retry);
panic_handler();
}
}
sync_cache();
console_flush();
switch_rtc_mode_2nd_stage();
if (monitor_entry) {
NOTICE("Jump to monitor at 0x%lx.\n", monitor_entry);
jump_to_monitor(monitor_entry, loader_2nd_entry);
} else {
NOTICE("Jump to loader_2nd at 0x%lx.\n", loader_2nd_entry);
jump_to_loader_2nd(loader_2nd_entry);
}
return 0;
}