xref: /openbmc/u-boot/arch/x86/lib/fsp/fsp_car.S (revision f13606b7)
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