mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-18 02:38:56 +00:00
aefaff8ed8
The call to FspInitEntry is done in arch/x86/lib/fsp/fsp_car.S so far. It worked pretty well but looks not that good. Apart from doing too much work than just enabling CAR, it cannot read the configuration data from device tree at that time. Now we want to move it a little bit later as part of init_sequence_f[] being called by board_init_f(). This way it looks and works better in the U-Boot initialization path. Due to FSP's design, after calling FspInitEntry it will not return to its caller, instead it jumps to a continuation function which is given by bootloader with a new stack in system memory. The original stack in the CAR is gone, but its content is perserved by FSP and described by a bootloader temporary memory HOB. Technically we can recover anything we had before in the previous stack, but that is way too complicated. To make life much easier, in the FSP continuation routine we just simply call fsp_init_done() and jump back to car_init_ret() to redo the whole board_init_f() initialization, but this time with a non-zero HOB list pointer saved in U-Boot's global data so that we can bypass the FspInitEntry for the second time. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Simon Glass <sjg@chromium.org> Tested-by: Andrew Bradford <andrew.bradford@kodakalaris.com> Tested-by: Simon Glass <sjg@chromium.org>
108 lines
2.3 KiB
ArmAsm
108 lines
2.3 KiB
ArmAsm
/*
|
|
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <asm/post.h>
|
|
|
|
.globl car_init
|
|
car_init:
|
|
/*
|
|
* Note: ebp holds the BIST value (built-in self test) so far, but ebp
|
|
* will be destroyed through the FSP call, thus we have to test the
|
|
* BIST value here before we call into FSP.
|
|
*/
|
|
test %ebp, %ebp
|
|
jz car_init_start
|
|
post_code(POST_BIST_FAILURE)
|
|
jmp die
|
|
|
|
car_init_start:
|
|
post_code(POST_CAR_START)
|
|
lea find_fsp_header_romstack, %esp
|
|
jmp find_fsp_header
|
|
|
|
find_fsp_header_ret:
|
|
/* EAX points to FSP_INFO_HEADER */
|
|
mov %eax, %ebp
|
|
|
|
/* sanity test */
|
|
cmp $CONFIG_FSP_ADDR, %eax
|
|
jb die
|
|
|
|
/* calculate TempRamInitEntry address */
|
|
mov 0x30(%ebp), %eax
|
|
add 0x1c(%ebp), %eax
|
|
|
|
/* call FSP TempRamInitEntry to setup temporary stack */
|
|
lea temp_ram_init_romstack, %esp
|
|
jmp *%eax
|
|
|
|
temp_ram_init_ret:
|
|
addl $4, %esp
|
|
cmp $0, %eax
|
|
jnz car_init_fail
|
|
|
|
post_code(POST_CAR_CPU_CACHE)
|
|
|
|
/*
|
|
* The FSP TempRamInit initializes the ecx and edx registers to
|
|
* point to a temporary but writable memory range (Cache-As-RAM).
|
|
* ecx: the start of this temporary memory range,
|
|
* edx: the end of this range.
|
|
*/
|
|
|
|
/* stack grows down from top of CAR */
|
|
movl %edx, %esp
|
|
subl $4, %esp
|
|
|
|
xor %esi, %esi
|
|
jmp car_init_done
|
|
|
|
.global fsp_init_done
|
|
fsp_init_done:
|
|
/*
|
|
* We come here from FspInit with eax pointing to the HOB list.
|
|
* Save eax to esi temporarily.
|
|
*/
|
|
movl %eax, %esi
|
|
|
|
car_init_done:
|
|
/*
|
|
* Re-initialize the ebp (BIST) to zero, as we already reach here
|
|
* which means we passed BIST testing before.
|
|
*/
|
|
xorl %ebp, %ebp
|
|
jmp car_init_ret
|
|
|
|
car_init_fail:
|
|
post_code(POST_CAR_FAILURE)
|
|
|
|
die:
|
|
hlt
|
|
jmp die
|
|
hlt
|
|
|
|
/*
|
|
* The function call before CAR initialization is tricky. It cannot
|
|
* be called using the 'call' instruction but only the 'jmp' with
|
|
* the help of a handcrafted stack in the ROM. The stack needs to
|
|
* contain the function return address as well as the parameters.
|
|
*/
|
|
.balign 4
|
|
find_fsp_header_romstack:
|
|
.long find_fsp_header_ret
|
|
|
|
.balign 4
|
|
temp_ram_init_romstack:
|
|
.long temp_ram_init_ret
|
|
.long temp_ram_init_params
|
|
temp_ram_init_params:
|
|
_dt_ucode_base_size:
|
|
/* These next two fields are filled in by ifdtool */
|
|
.long 0 /* microcode base */
|
|
.long 0 /* microcode size */
|
|
.long CONFIG_SYS_MONITOR_BASE /* code region base */
|
|
.long CONFIG_SYS_MONITOR_LEN /* code region size */
|