summaryrefslogtreecommitdiff
path: root/arch/x86/lib/fsp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/lib/fsp')
-rw-r--r--arch/x86/lib/fsp/Makefile2
-rw-r--r--arch/x86/lib/fsp/fsp_car.S124
-rw-r--r--arch/x86/lib/fsp/fsp_dram.c81
3 files changed, 207 insertions, 0 deletions
diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile
index 1b9b0e279a..3a2bac0636 100644
--- a/arch/x86/lib/fsp/Makefile
+++ b/arch/x86/lib/fsp/Makefile
@@ -4,4 +4,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-y += fsp_car.o
+obj-y += fsp_dram.o
obj-y += fsp_support.o
diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp/fsp_car.S
new file mode 100644
index 0000000000..5e09568b85
--- /dev/null
+++ b/arch/x86/lib/fsp/fsp_car.S
@@ -0,0 +1,124 @@
+/*
+ * 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
+
+ /*
+ * TODO:
+ *
+ * According to FSP architecture spec, the fsp_init() will not return
+ * to its caller, instead it requires the bootloader to provide a
+ * so-called continuation function to pass into the FSP as a parameter
+ * of fsp_init, and fsp_init() will call that continuation function
+ * directly.
+ *
+ * The call to fsp_init() may need to be moved out of the car_init()
+ * to cpu_init_f() with the help of some inline assembly codes.
+ * Note there is another issue that fsp_init() will setup another stack
+ * using the fsp_init parameter stack_top after DRAM is initialized,
+ * which means any data on the previous stack (on the CAR) gets lost
+ * (ie: U-Boot global_data). FSP is supposed to support such scenario,
+ * however it does not work. This should be revisited in the future.
+ */
+ movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax
+ xorl %edx, %edx
+ xorl %ecx, %ecx
+ call fsp_init
+
+.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
+ /*
+ * 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 */
diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c
new file mode 100644
index 0000000000..4c0a7c82ca
--- /dev/null
+++ b/arch/x86/lib/fsp/fsp_dram.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/fsp/fsp_support.h>
+#include <asm/e820.h>
+#include <asm/post.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+ phys_size_t ram_size = 0;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
+
+ hdr = gd->arch.hob_list;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM ||
+ res_desc->type == RES_MEM_RESERVED) {
+ ram_size += res_desc->len;
+ }
+ }
+ hdr = get_next_hob(hdr);
+ }
+
+ gd->ram_size = ram_size;
+ post_code(POST_DRAM);
+
+ return 0;
+}
+
+void dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = 0;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+}
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return fsp_get_usable_lowmem_top(gd->arch.hob_list);
+}
+
+unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
+{
+ unsigned num_entries = 0;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
+
+ hdr = gd->arch.hob_list;
+
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ entries[num_entries].addr = res_desc->phys_start;
+ entries[num_entries].size = res_desc->len;
+
+ if (res_desc->type == RES_SYS_MEM)
+ entries[num_entries].type = E820_RAM;
+ else if (res_desc->type == RES_MEM_RESERVED)
+ entries[num_entries].type = E820_RESERVED;
+ }
+ hdr = get_next_hob(hdr);
+ num_entries++;
+ }
+
+ return num_entries;
+}