1/* 2 * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7#include <config.h> 8#include <asm/post.h> 9 10.globl car_init 11car_init: 12 /* 13 * Note: ebp holds the BIST value (built-in self test) so far, but ebp 14 * will be destroyed through the FSP call, thus we have to test the 15 * BIST value here before we call into FSP. 16 */ 17 test %ebp, %ebp 18 jz car_init_start 19 post_code(POST_BIST_FAILURE) 20 jmp die 21 22car_init_start: 23 post_code(POST_CAR_START) 24 lea find_fsp_header_romstack, %esp 25 jmp find_fsp_header 26 27find_fsp_header_ret: 28 /* EAX points to FSP_INFO_HEADER */ 29 mov %eax, %ebp 30 31 /* sanity test */ 32 cmp $CONFIG_FSP_ADDR, %eax 33 jb die 34 35 /* calculate TempRamInitEntry address */ 36 mov 0x30(%ebp), %eax 37 add 0x1c(%ebp), %eax 38 39 /* call FSP TempRamInitEntry to setup temporary stack */ 40 lea temp_ram_init_romstack, %esp 41 jmp *%eax 42 43temp_ram_init_ret: 44 addl $4, %esp 45 cmp $0, %eax 46 jnz car_init_fail 47 48 post_code(POST_CAR_CPU_CACHE) 49 50 /* 51 * The FSP TempRamInit initializes the ecx and edx registers to 52 * point to a temporary but writable memory range (Cache-As-RAM). 53 * ecx: the start of this temporary memory range, 54 * edx: the end of this range. 55 */ 56 57 /* stack grows down from top of CAR */ 58 movl %edx, %esp 59 60 /* 61 * TODO: 62 * 63 * According to FSP architecture spec, the fsp_init() will not return 64 * to its caller, instead it requires the bootloader to provide a 65 * so-called continuation function to pass into the FSP as a parameter 66 * of fsp_init, and fsp_init() will call that continuation function 67 * directly. 68 * 69 * The call to fsp_init() may need to be moved out of the car_init() 70 * to cpu_init_f() with the help of some inline assembly codes. 71 * Note there is another issue that fsp_init() will setup another stack 72 * using the fsp_init parameter stack_top after DRAM is initialized, 73 * which means any data on the previous stack (on the CAR) gets lost 74 * (ie: U-Boot global_data). FSP is supposed to support such scenario, 75 * however it does not work. This should be revisited in the future. 76 */ 77 movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax 78 xorl %edx, %edx 79 xorl %ecx, %ecx 80 call fsp_init 81 82.global fsp_init_done 83fsp_init_done: 84 /* 85 * We come here from FspInit with eax pointing to the HOB list. 86 * Save eax to esi temporarily. 87 */ 88 movl %eax, %esi 89 /* 90 * Re-initialize the ebp (BIST) to zero, as we already reach here 91 * which means we passed BIST testing before. 92 */ 93 xorl %ebp, %ebp 94 jmp car_init_ret 95 96car_init_fail: 97 post_code(POST_CAR_FAILURE) 98 99die: 100 hlt 101 jmp die 102 hlt 103 104 /* 105 * The function call before CAR initialization is tricky. It cannot 106 * be called using the 'call' instruction but only the 'jmp' with 107 * the help of a handcrafted stack in the ROM. The stack needs to 108 * contain the function return address as well as the parameters. 109 */ 110 .balign 4 111find_fsp_header_romstack: 112 .long find_fsp_header_ret 113 114 .balign 4 115temp_ram_init_romstack: 116 .long temp_ram_init_ret 117 .long temp_ram_init_params 118temp_ram_init_params: 119_dt_ucode_base_size: 120 /* These next two fields are filled in by ifdtool */ 121 .long 0 /* microcode base */ 122 .long 0 /* microcode size */ 123 .long CONFIG_SYS_MONITOR_BASE /* code region base */ 124 .long CONFIG_SYS_MONITOR_LEN /* code region size */ 125