mirror of
https://github.com/sipeed/LicheeRV-Nano-Build.git
synced 2026-11-09 18:04:55 -06:00
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.
614 lines
16 KiB
C
614 lines
16 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>
|
|
#include <emmc/emmc.h>
|
|
#include <cv_spi_nand.h>
|
|
|
|
uint64_t load_addr = 0x0c000;
|
|
uint64_t run_addr = 0x8000C000;
|
|
uint64_t reading_size = 0x020000;
|
|
|
|
struct _time_records *time_records = (void *)TIME_RECORDS_ADDR;
|
|
struct fip_param1 *fip_param1 = (void *)PARAM1_BASE;
|
|
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(void)
|
|
{
|
|
#ifndef ENABLE_BOOT0
|
|
int retry = 0;
|
|
|
|
retry_from_flash:
|
|
for (retry = 0; retry < p_rom_api_get_number_of_retries(); retry++) {
|
|
if (load_param2(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 param2 (%d).\n", retry);
|
|
panic_handler();
|
|
}
|
|
}
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
static int emmc_read_fip_bl2(uint32_t offset, uint32_t size, uintptr_t buf)
|
|
{
|
|
int lba = 0;
|
|
|
|
if (((offset & EMMC_BLOCK_MASK) != 0) || ((buf & EMMC_BLOCK_MASK) != 0) || ((size & EMMC_BLOCK_MASK) != 0))
|
|
return -22;
|
|
|
|
lba = offset / EMMC_BLOCK_SIZE;
|
|
|
|
// INFO("%s offset %x,lba %d, size %d, dst buf 0x%lx\n", __func__, offset, lba, size, buf);
|
|
|
|
if (size != emmc_partition_read_blocks(EMMC_PARTITION_BOOT1, lba, buf, size))
|
|
return -5;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int load_data_from_storage(void *buffer, uint32_t offset, uint32_t size, int retry)
|
|
{
|
|
static int is_get_boot_src;
|
|
static int boot_src;
|
|
|
|
if (!is_get_boot_src) {
|
|
boot_src = p_rom_api_get_boot_src();
|
|
is_get_boot_src = 1;
|
|
|
|
/* reinit eMMC */
|
|
if (boot_src == BOOT_SRC_EMMC)
|
|
bm_emmc_init();
|
|
}
|
|
|
|
//use BL2 eMMC driver to load image
|
|
if (boot_src == BOOT_SRC_EMMC) {
|
|
return emmc_read_fip_bl2(offset, size, (uintptr_t)buffer);
|
|
} else {
|
|
return p_rom_api_load_image(buffer, offset, size, retry);
|
|
}
|
|
}
|
|
|
|
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 = load_data_from_storage((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);
|
|
|
|
switch (p_rom_api_get_boot_src()) {
|
|
case BOOT_SRC_UART:
|
|
// case BOOT_SRC_SD:
|
|
// case BOOT_SRC_USB:
|
|
break;
|
|
|
|
default:
|
|
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 = load_data_from_storage((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;
|
|
}
|
|
|
|
#ifdef ENABLE_BURN_BUTTON
|
|
|
|
int button_usb_down_pressed(void)
|
|
{
|
|
// Modify the GPIO configuration as needed!!!!!!!!!
|
|
uint8_t gpio_grp = GPIO_GRP, gpio_pin = GPIO_PIN; // XGPIOB[3];
|
|
NOTICE("gpio_grp = %d gpio_pin = %d\n", gpio_grp, gpio_pin);
|
|
|
|
// gpio base addr: gpioa, gpiob, gpioc, gpiod, pwr_gpio;
|
|
uint32_t gpio_base[5] = { 0x03020000, 0x03021000, 0x03022000, 0x03023000, 0x05021000 };
|
|
uint32_t gpio_direction_addr = gpio_base[gpio_grp] + 0x4;
|
|
uint32_t gpio_value_addr = gpio_base[gpio_grp] + 0x50;
|
|
uint32_t val = 0x1;
|
|
|
|
/* pinmux config */
|
|
// mmio_write_32(0x03001098, 0x3);
|
|
|
|
/* open internel pull up */
|
|
// mmio_write_32(0x05027020, 0x44);
|
|
|
|
/* gpio input mode */
|
|
val = mmio_read_32(gpio_direction_addr) & (~(1 << gpio_pin));
|
|
mmio_write_32(gpio_direction_addr, val);
|
|
|
|
/* gpio debouncing */
|
|
val = (mmio_read_32(gpio_value_addr) >> gpio_pin) & 0x1;
|
|
NOTICE("key value = %u (key down should be 0)\n", val);
|
|
if (!val) {
|
|
mdelay(10);
|
|
val = (mmio_read_32(gpio_value_addr) >> gpio_pin) & 0x1;
|
|
NOTICE("repeat key value = %u (key down should be 0)\n", val);
|
|
return !val;
|
|
}
|
|
return 0; // pressed:1 unpressed:0
|
|
}
|
|
|
|
int load_uboot(void *image_buf, int retry)
|
|
{
|
|
int ret = -1;
|
|
int reading_size = 0;
|
|
|
|
reading_size = ROUND_UP(fip_param2.loader_2nd_b_size, BLOCK_SIZE);
|
|
NOTICE("reading_size:%x, addr:=0x%x\n", reading_size, fip_param2.loader_2nd_b_loadaddr);
|
|
ret = load_data_from_storage(image_buf, fip_param2.loader_2nd_b_loadaddr, reading_size, retry);
|
|
if (ret < 0) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
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 = load_data_from_storage(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);
|
|
|
|
#ifdef ENABLE_BURN_BUTTON
|
|
if (button_usb_down_pressed()) {
|
|
NOTICE("usb_down button pressed.\n");
|
|
mmio_write_32(BOOT_SOURCE_FLAG_ADDR, MAGIC_NUM_USB_DL);
|
|
loader_2nd_header->runaddr = CONFIG_SYS_TEXT_BASE;
|
|
ret = load_uboot((void *)loader_2nd_header->runaddr, retry);
|
|
if (ret < 0) {
|
|
return -1;
|
|
}
|
|
goto done;
|
|
}
|
|
#endif
|
|
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;
|
|
}
|
|
#ifdef ENABLE_BURN_BUTTON
|
|
done:
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
int load_loader_2nd_alios(int retry, uint64_t *loader_2nd_entry)
|
|
{
|
|
void *image_buf;
|
|
int ret = -1;
|
|
#ifdef BOOT_SPINOR
|
|
load_addr = 0x0c000;
|
|
#endif
|
|
|
|
#ifdef BOOT_EMMC
|
|
load_addr = 0x00000;
|
|
#endif
|
|
|
|
#ifdef BOOT_SPINAND
|
|
load_addr = 0x280000;
|
|
#endif
|
|
uint64_t loadaddr_alios = load_addr;
|
|
uint64_t runaddr_alios = run_addr;
|
|
uint64_t size_alios = reading_size;
|
|
|
|
image_buf = (void *)runaddr_alios;
|
|
NOTICE("loadaddr_alios:0x%lx runaddr_alios:0x%lx.\n", loadaddr_alios, runaddr_alios);
|
|
|
|
#ifdef BOOT_SPINAND
|
|
/* SPI-NAND uses the in-tree raw-read driver: read linearly by physical
|
|
* page, bypassing the ROM API FIP (FIPH/fip_vector) scan. The single-image
|
|
* RTT boot partition is not in the NAND-FIP layout, so the ROM API returns
|
|
* FIP0NC. get_nand_info() self-calibrates the geometry on the first read.
|
|
* Compiled only into spinand boot0 images; the full-FIP paths are untouched,
|
|
* symmetric with cv180x. */
|
|
{
|
|
static int nand_info_ready;
|
|
|
|
if (!nand_info_ready) {
|
|
get_nand_info();
|
|
nand_info_ready = 1;
|
|
}
|
|
ret = cv_spi_nand_read_data(image_buf, loadaddr_alios, size_alios);
|
|
}
|
|
#else
|
|
ret = p_rom_api_load_image(image_buf, loadaddr_alios, size_alios, retry);
|
|
#endif
|
|
/* Must check the return value: the original code ignored ret and jumped to
|
|
* run_addr executing garbage on a failed load, causing a panic. */
|
|
if (ret < 0) {
|
|
ERROR("load loader_2nd_alios failed (%d)\n", ret);
|
|
return ret;
|
|
}
|
|
NOTICE("image_buf:0x%lx.\n", *((uint64_t *)runaddr_alios));
|
|
if (security_is_tee_enabled()) {
|
|
ret = dec_verify_image(image_buf,size_alios, 0, fip_param1);
|
|
if (ret < 0) {
|
|
ERROR("verify alios boot0 failed (%d)\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
sys_switch_all_to_pll();
|
|
|
|
*loader_2nd_entry = run_addr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int load_rest(void)
|
|
{
|
|
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();
|
|
#ifndef ENABLE_BOOT0
|
|
#ifdef FSBL_FASTBOOT
|
|
mmio_write_32(0x030020B8, 0x00030009); // improve axi clock from 300m to 500m
|
|
#endif
|
|
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();
|
|
}
|
|
}
|
|
|
|
#ifdef FSBL_FASTBOOT
|
|
mmio_write_32(0x030020B8, 0x00050009); // restore axi clock from 500m to 300m
|
|
#endif
|
|
sync_cache();
|
|
console_flush();
|
|
|
|
// switch_rtc_mode_2nd_stage();
|
|
#else
|
|
#ifdef ENABLE_FASTBOOT0
|
|
mmio_write_32(0x030020B8, 0x00030009);
|
|
#endif
|
|
if (load_loader_2nd_alios(retry, &loader_2nd_entry) < 0)
|
|
return -1;
|
|
#ifdef ENABLE_FASTBOOT0
|
|
mmio_write_32(0x030020B8, 0x00050009);
|
|
#endif
|
|
sync_cache();
|
|
|
|
// switch_rtc_mode_2nd_stage();
|
|
#ifdef __riscv
|
|
/*
|
|
* RISC-V: jump_to_loader_2nd() is empty; jump_to_monitor() calls the
|
|
* image directly in M-mode, which is how the loaded image is started.
|
|
* AArch64: leave monitor_entry at 0 so jump_to_loader_2nd() drops to
|
|
* EL2-NS. jump_to_monitor() would enter the image at secure EL3 with
|
|
* BL31 params, and the image loaded here is not a BL31 monitor.
|
|
*/
|
|
monitor_entry = run_addr;
|
|
#endif
|
|
#endif
|
|
|
|
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;
|
|
}
|