From b2e02d28653edac48d6def9791f2fa0ebc491498 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:36 +0800 Subject: x86: Add basic support to queensbay platform and crownbay board Implement minimum required functions for the basic support to queensbay platform and crownbay board. Currently the implementation is to call fsp_init() in the car_init(). We may move that call to cpu_init_f() in the future. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/Makefile | 9 +++ arch/x86/cpu/queensbay/tnc.c | 48 ++++++++++++++ arch/x86/cpu/queensbay/tnc_car.S | 127 ++++++++++++++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc_dram.c | 78 +++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc_pci.c | 61 ++++++++++++++++++ 5 files changed, 323 insertions(+) create mode 100644 arch/x86/cpu/queensbay/Makefile create mode 100644 arch/x86/cpu/queensbay/tnc.c create mode 100644 arch/x86/cpu/queensbay/tnc_car.S create mode 100644 arch/x86/cpu/queensbay/tnc_dram.c create mode 100644 arch/x86/cpu/queensbay/tnc_pci.c (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile new file mode 100644 index 0000000000..ace04ca4d0 --- /dev/null +++ b/arch/x86/cpu/queensbay/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2014, Bin Meng +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += tnc_car.o tnc_dram.o tnc.o +obj-y += fsp_configs.o fsp_support.o +obj-$(CONFIG_PCI) += tnc_pci.o diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c new file mode 100644 index 0000000000..8b9815fa00 --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +int arch_cpu_init(void) +{ + post_code(POST_CPU_INIT); +#ifdef CONFIG_SYS_X86_TSC_TIMER + timer_set_base(rdtsc()); +#endif + + return x86_cpu_init_f(); +} + +int print_cpuinfo(void) +{ + post_code(POST_CPU_INFO); + return default_print_cpuinfo(); +} + +void reset_cpu(ulong addr) +{ + /* cold reset */ + outb(0x06, PORT_RESET); +} + +void board_final_cleanup(void) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_BOOT): "); + status = fsp_notify(NULL, INIT_PHASE_BOOT); + if (status != FSP_SUCCESS) + debug("fail, error code %x\n", status); + else + debug("OK\n"); + + return; +} diff --git a/arch/x86/cpu/queensbay/tnc_car.S b/arch/x86/cpu/queensbay/tnc_car.S new file mode 100644 index 0000000000..6834a6413d --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc_car.S @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +.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_LOCATION, %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: + .long ucode_start /* microcode base */ + .long ucode_size /* microcode size */ + .long CONFIG_SYS_MONITOR_BASE /* code region base */ + .long CONFIG_SYS_MONITOR_LEN /* code region size */ + + .balign 4 +ucode_start: + .include "arch/x86/cpu/queensbay/M0220661105.inc" +ucode_size = ( . - ucode_start) diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c new file mode 100644 index 0000000000..dbc17102da --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc_dram.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + phys_size_t ram_size = 0; + union hob_pointers_t hob; + + hob.raw = gd->arch.hob_list; + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == HOB_TYPE_RES_DESC) { + if (hob.res_desc->type == RES_SYS_MEM || + hob.res_desc->type == RES_MEM_RESERVED) { + ram_size += hob.res_desc->len; + } + } + hob.raw = GET_NEXT_HOB(hob); + } + + 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 get_usable_lowmem_top(gd->arch.hob_list); +} + +unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) +{ + unsigned num_entries = 0; + + union hob_pointers_t hob; + + hob.raw = gd->arch.hob_list; + + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == HOB_TYPE_RES_DESC) { + entries[num_entries].addr = hob.res_desc->phys_start; + entries[num_entries].size = hob.res_desc->len; + + if (hob.res_desc->type == RES_SYS_MEM) + entries[num_entries].type = E820_RAM; + else if (hob.res_desc->type == RES_MEM_RESERVED) + entries[num_entries].type = E820_RESERVED; + } + hob.raw = GET_NEXT_HOB(hob); + num_entries++; + } + + return num_entries; +} diff --git a/arch/x86/cpu/queensbay/tnc_pci.c b/arch/x86/cpu/queensbay/tnc_pci.c new file mode 100644 index 0000000000..39bff49c8d --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc_pci.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +void board_pci_setup_hose(struct pci_controller *hose) +{ + hose->first_busno = 0; + hose->last_busno = 0; + + /* PCI memory space */ + pci_set_region(hose->regions + 0, + CONFIG_PCI_MEM_BUS, + CONFIG_PCI_MEM_PHYS, + CONFIG_PCI_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 1, + CONFIG_PCI_IO_BUS, + CONFIG_PCI_IO_PHYS, + CONFIG_PCI_IO_SIZE, + PCI_REGION_IO); + + pci_set_region(hose->regions + 2, + CONFIG_PCI_PREF_BUS, + CONFIG_PCI_PREF_PHYS, + CONFIG_PCI_PREF_SIZE, + PCI_REGION_PREFETCH); + + pci_set_region(hose->regions + 3, + 0, + 0, + gd->ram_size, + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); + + hose->region_count = 4; +} + +int board_pci_post_scan(struct pci_controller *hose) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); + status = fsp_notify(NULL, INIT_PHASE_PCI); + if (status != FSP_SUCCESS) + debug("fail, error code %x\n", status); + else + debug("OK\n"); + + return 0; +} -- cgit From 0f61de8d9dba4ebfc4ea4b2da7f91adc937b3875 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 17 Dec 2014 15:50:37 +0800 Subject: x86: Convert microcode format to device-tree-only To avoid having two microcode formats, adjust the build system to support obtaining the microcode from the device tree, even in the case where it must be made available before the device tree can be accessed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/cpu/queensbay/tnc_car.S | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/tnc_car.S b/arch/x86/cpu/queensbay/tnc_car.S index 6834a6413d..2e9139eb8c 100644 --- a/arch/x86/cpu/queensbay/tnc_car.S +++ b/arch/x86/cpu/queensbay/tnc_car.S @@ -116,12 +116,9 @@ temp_ram_init_romstack: .long temp_ram_init_ret .long temp_ram_init_params temp_ram_init_params: - .long ucode_start /* microcode base */ - .long ucode_size /* microcode size */ +_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 */ - - .balign 4 -ucode_start: - .include "arch/x86/cpu/queensbay/M0220661105.inc" -ucode_size = ( . - ucode_start) -- cgit From 58f542de30e3bae9845726af36e0e25b5b458e8c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:40 +0800 Subject: x86: Add queensbay and crownbay Kconfig files Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/Kconfig | 79 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 arch/x86/cpu/queensbay/Kconfig (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig new file mode 100644 index 0000000000..56fe85ccad --- /dev/null +++ b/arch/x86/cpu/queensbay/Kconfig @@ -0,0 +1,79 @@ +# +# Copyright (C) 2014, Bin Meng +# +# SPDX-License-Identifier: GPL-2.0+ +# + +config INTEL_QUEENSBAY + bool + select HAVE_FSP + select HAVE_CMC + +if INTEL_QUEENSBAY + +config HAVE_FSP + bool "Add an Firmware Support Package binary" + help + Select this option to add an Firmware Support Package binary to + the resulting U-Boot image. It is a binary blob which U-Boot uses + to set up SDRAM and other chipset specific initialization. + + Note: Without this binary U-Boot will not be able to set up its + SDRAM so will not boot. + +config FSP_FILE + string "Firmware Support Package binary filename" + depends on HAVE_FSP + default "fsp.bin" + help + The filename of the file to use as Firmware Support Package binary + in the board directory. + +config FSP_LOCATION + hex "Firmware Support Package binary location" + depends on HAVE_FSP + default 0xfffc0000 + help + FSP is not Position Independent Code (PIC) and the whole FSP has to + be rebased if it is placed at a location which is different from the + perferred base address specified during the FSP build. Use Intel's + Binary Configuration Tool (BCT) to do the rebase. + + The default base address of 0xfffc0000 indicates that the binary must + be located at offset 0xc0000 from the beginning of a 1MB flash device. + +config FSP_TEMP_RAM_ADDR + hex + default 0x2000000 + help + Stack top address which is used in FspInit after DRAM is ready and + CAR is disabled. + +config HAVE_CMC + bool "Add a Chipset Micro Code state machine binary" + help + Select this option to add a Chipset Micro Code state machine binary + to the resulting U-Boot image. It is a 64K data block of machine + specific code which must be put in the flash for the processor to + access when powered up before system BIOS is executed. + +config CMC_FILE + string "Chipset Micro Code state machine filename" + depends on HAVE_CMC + default "cmc.bin" + help + The filename of the file to use as Chipset Micro Code state machine + binary in the board directory. + +config CMC_LOCATION + hex "Chipset Micro Code state machine binary location" + depends on HAVE_CMC + default 0xfffb0000 + help + The location of the CMC binary is determined by a strap. It must be + put in flash at a location matching the strap-determined base address. + + The default base address of 0xfffb0000 indicates that the binary must + be located at offset 0xb0000 from the beginning of a 1MB flash device. + +endif -- cgit From 8c5224c9f5c8a24ff5153f018e10a3ac4da5783a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:42 +0800 Subject: x86: Use consistent name XXX_ADDR for binary blob flash address Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/Kconfig | 4 ++-- arch/x86/cpu/queensbay/fsp_support.c | 2 +- arch/x86/cpu/queensbay/tnc_car.S | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig index 56fe85ccad..f6b52010c3 100644 --- a/arch/x86/cpu/queensbay/Kconfig +++ b/arch/x86/cpu/queensbay/Kconfig @@ -29,7 +29,7 @@ config FSP_FILE The filename of the file to use as Firmware Support Package binary in the board directory. -config FSP_LOCATION +config FSP_ADDR hex "Firmware Support Package binary location" depends on HAVE_FSP default 0xfffc0000 @@ -65,7 +65,7 @@ config CMC_FILE The filename of the file to use as Chipset Micro Code state machine binary in the board directory. -config CMC_LOCATION +config CMC_ADDR hex "Chipset Micro Code state machine binary location" depends on HAVE_CMC default 0xfffb0000 diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c index df3bbd07c9..f830eeb33d 100644 --- a/arch/x86/cpu/queensbay/fsp_support.c +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -64,7 +64,7 @@ u32 __attribute__((optimize("O0"))) find_fsp_header(void) volatile register u8 *fsp asm("eax"); /* Initalize the FSP base */ - fsp = (u8 *)CONFIG_FSP_LOCATION; + fsp = (u8 *)CONFIG_FSP_ADDR; /* Check the FV signature, _FVH */ if (((struct fv_header_t *)fsp)->sign == 0x4856465F) { diff --git a/arch/x86/cpu/queensbay/tnc_car.S b/arch/x86/cpu/queensbay/tnc_car.S index 2e9139eb8c..5e09568b85 100644 --- a/arch/x86/cpu/queensbay/tnc_car.S +++ b/arch/x86/cpu/queensbay/tnc_car.S @@ -29,7 +29,7 @@ find_fsp_header_ret: mov %eax, %ebp /* sanity test */ - cmp $CONFIG_FSP_LOCATION, %eax + cmp $CONFIG_FSP_ADDR, %eax jb die /* calculate TempRamInitEntry address */ -- cgit From adfe3b247a7a281931f0fd865e9d00600e9dd384 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:44 +0800 Subject: x86: crownbay: Add SPI flash support The Crown Bay board has an SST25VF016B flash connected to the Tunnel Creek processor SPI controller used as the BIOS media where U-Boot is stored. Enable this flash support. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/tnc.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index 8b9815fa00..8637cdca2d 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -6,18 +6,42 @@ #include #include +#include #include +#include #include #include +static void unprotect_spi_flash(void) +{ + u32 bc; + + bc = pci_read_config32(PCH_LPC_DEV, 0xd8); + bc |= 0x1; /* unprotect the flash */ + pci_write_config32(PCH_LPC_DEV, 0xd8, bc); +} + int arch_cpu_init(void) { + struct pci_controller *hose; + int ret; + post_code(POST_CPU_INIT); #ifdef CONFIG_SYS_X86_TSC_TIMER timer_set_base(rdtsc()); #endif - return x86_cpu_init_f(); + ret = x86_cpu_init_f(); + if (ret) + return ret; + + ret = pci_early_init_hose(&hose); + if (ret) + return ret; + + unprotect_spi_flash(); + + return 0; } int print_cpuinfo(void) -- cgit From aada6276c68daf0229442aa8bf6e60aae4c4fd0d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:46 +0800 Subject: x86: crownbay: Add SDHCI support There are two standard SD card slots on the Crown Bay board, which are connected to the Topcliff PCH SDIO controllers. Enable the SDHC support so that we can use them. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/topcliff.c | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/queensbay/topcliff.c (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile index ace04ca4d0..2c2ec01ed2 100644 --- a/arch/x86/cpu/queensbay/Makefile +++ b/arch/x86/cpu/queensbay/Makefile @@ -4,6 +4,6 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += tnc_car.o tnc_dram.o tnc.o +obj-y += tnc_car.o tnc_dram.o tnc.o topcliff.o obj-y += fsp_configs.o fsp_support.o obj-$(CONFIG_PCI) += tnc_pci.o diff --git a/arch/x86/cpu/queensbay/topcliff.c b/arch/x86/cpu/queensbay/topcliff.c new file mode 100644 index 0000000000..b01422a965 --- /dev/null +++ b/arch/x86/cpu/queensbay/topcliff.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +static struct pci_device_id mmc_supported[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1 }, + { } +}; + +int cpu_mmc_init(bd_t *bis) +{ + struct sdhci_host *mmc_host; + pci_dev_t devbusfn; + u32 iobase; + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(mmc_supported); i++) { + devbusfn = pci_find_devices(mmc_supported, i); + if (devbusfn == -1) + return -ENODEV; + + mmc_host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); + if (!mmc_host) + return -ENOMEM; + + mmc_host->name = "Topcliff SDHCI"; + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); + mmc_host->ioaddr = (void *)iobase; + mmc_host->quirks = 0; + ret = add_sdhci(mmc_host, 0, 0); + if (ret) + return ret; + } + + return 0; +} -- cgit From 255fd5caa5dda7f1028843753562eff58f3855bc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:49 +0800 Subject: x86: Clean up the FSP support codes This is the follow-on patch to clean up the FSP support codes: - Remove the _t suffix on the structures defines - Use __packed for structure defines - Use U-Boot's assert() - Use standard bool true/false - Remove read_unaligned64() - Use memcmp() in the compare_guid() - Remove the cast in the memset() call - Replace some magic numbers with macros - Use panic() when no valid FSP image header is found - Change some FSP utility routines to use an fsp_ prefix - Add comment blocks for asm_continuation and fsp_init_done - Remove some casts in find_fsp_header() - Change HOB access macros to static inline routines - Add comments to mention find_fsp_header() may be called in a stackless environment - Add comments to mention init(¶ms) in fsp_init() cannot be removed Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/fsp_support.c | 253 ++++++++++++++++------------------- arch/x86/cpu/queensbay/tnc_dram.c | 18 +-- 3 files changed, 129 insertions(+), 144 deletions(-) (limited to 'arch/x86/cpu/queensbay') diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c index aef18fcb59..af28e457f6 100644 --- a/arch/x86/cpu/queensbay/fsp_configs.c +++ b/arch/x86/cpu/queensbay/fsp_configs.c @@ -8,7 +8,7 @@ #include #include -void update_fsp_upd(struct upd_region_t *fsp_upd) +void update_fsp_upd(struct upd_region *fsp_upd) { /* Override any UPD setting if required */ diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c index f830eeb33d..ef1916b2e7 100644 --- a/arch/x86/cpu/queensbay/fsp_support.c +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -9,68 +9,49 @@ #include #include -/** - * Reads a 64-bit value from memory that may be unaligned. - * - * This function returns the 64-bit value pointed to by buf. The function - * guarantees that the read operation does not produce an alignment fault. - * - * If the buf is NULL, then ASSERT(). - * - * @buf: Pointer to a 64-bit value that may be unaligned. - * - * @return: The 64-bit value read from buf. - */ -static u64 read_unaligned64(const u64 *buf) -{ - ASSERT(buf != NULL); - - return *buf; -} - /** * Compares two GUIDs * - * If the GUIDs are identical then TRUE is returned. - * If there are any bit differences in the two GUIDs, then FALSE is returned. - * - * If guid1 is NULL, then ASSERT(). - * If guid2 is NULL, then ASSERT(). + * If the GUIDs are identical then true is returned. + * If there are any bit differences in the two GUIDs, then false is returned. * * @guid1: A pointer to a 128 bit GUID. * @guid2: A pointer to a 128 bit GUID. * - * @retval TRUE: guid1 and guid2 are identical. - * @retval FALSE: guid1 and guid2 are not identical. + * @retval true: guid1 and guid2 are identical. + * @retval false: guid1 and guid2 are not identical. */ -static unsigned char compare_guid(const struct efi_guid_t *guid1, - const struct efi_guid_t *guid2) +static bool compare_guid(const struct efi_guid *guid1, + const struct efi_guid *guid2) { - u64 guid1_low; - u64 guid2_low; - u64 guid1_high; - u64 guid2_high; - - guid1_low = read_unaligned64((const u64 *)guid1); - guid2_low = read_unaligned64((const u64 *)guid2); - guid1_high = read_unaligned64((const u64 *)guid1 + 1); - guid2_high = read_unaligned64((const u64 *)guid2 + 1); - - return (unsigned char)(guid1_low == guid2_low && guid1_high == guid2_high); + if (memcmp(guid1, guid2, sizeof(struct efi_guid)) == 0) + return true; + else + return false; } u32 __attribute__((optimize("O0"))) find_fsp_header(void) { + /* + * This function may be called before the a stack is established, + * so special care must be taken. First, it cannot declare any local + * variable using stack. Only register variable can be used here. + * Secondly, some compiler version will add prolog or epilog code + * for the C function. If so the function call may not work before + * stack is ready. + * + * GCC 4.8.1 has been verified to be working for the following codes. + */ volatile register u8 *fsp asm("eax"); /* Initalize the FSP base */ fsp = (u8 *)CONFIG_FSP_ADDR; /* Check the FV signature, _FVH */ - if (((struct fv_header_t *)fsp)->sign == 0x4856465F) { + if (((struct fv_header *)fsp)->sign == EFI_FVH_SIGNATURE) { /* Go to the end of the FV header and align the address */ - fsp += ((struct fv_header_t *)fsp)->ext_hdr_off; - fsp += ((struct fv_ext_header_t *)fsp)->ext_hdr_size; + fsp += ((struct fv_header *)fsp)->ext_hdr_off; + fsp += ((struct fv_ext_header *)fsp)->ext_hdr_size; fsp = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8); } else { fsp = 0; @@ -78,20 +59,27 @@ u32 __attribute__((optimize("O0"))) find_fsp_header(void) /* Check the FFS GUID */ if (fsp && - (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[0] == 0x912740BE) && - (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[1] == 0x47342284) && - (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[2] == 0xB08471B9) && - (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[3] == 0x0C3F3527)) { + ((struct ffs_file_header *)fsp)->name.data1 == FSP_GUID_DATA1 && + ((struct ffs_file_header *)fsp)->name.data2 == FSP_GUID_DATA2 && + ((struct ffs_file_header *)fsp)->name.data3 == FSP_GUID_DATA3 && + ((struct ffs_file_header *)fsp)->name.data4[0] == FSP_GUID_DATA4_0 && + ((struct ffs_file_header *)fsp)->name.data4[1] == FSP_GUID_DATA4_1 && + ((struct ffs_file_header *)fsp)->name.data4[2] == FSP_GUID_DATA4_2 && + ((struct ffs_file_header *)fsp)->name.data4[3] == FSP_GUID_DATA4_3 && + ((struct ffs_file_header *)fsp)->name.data4[4] == FSP_GUID_DATA4_4 && + ((struct ffs_file_header *)fsp)->name.data4[5] == FSP_GUID_DATA4_5 && + ((struct ffs_file_header *)fsp)->name.data4[6] == FSP_GUID_DATA4_6 && + ((struct ffs_file_header *)fsp)->name.data4[7] == FSP_GUID_DATA4_7) { /* Add the FFS header size to find the raw section header */ - fsp += sizeof(struct ffs_file_header_t); + fsp += sizeof(struct ffs_file_header); } else { fsp = 0; } if (fsp && - ((struct raw_section_t *)fsp)->type == EFI_SECTION_RAW) { + ((struct raw_section *)fsp)->type == EFI_SECTION_RAW) { /* Add the raw section header size to find the FSP header */ - fsp += sizeof(struct raw_section_t); + fsp += sizeof(struct raw_section); } else { fsp = 0; } @@ -99,7 +87,7 @@ u32 __attribute__((optimize("O0"))) find_fsp_header(void) return (u32)fsp; } -void fsp_continue(struct shared_data_t *shared_data, u32 status, void *hob_list) +void fsp_continue(struct shared_data *shared_data, u32 status, void *hob_list) { u32 stack_len; u32 stack_base; @@ -107,18 +95,18 @@ void fsp_continue(struct shared_data_t *shared_data, u32 status, void *hob_list) post_code(POST_MRC); - ASSERT(status == 0); + assert(status == 0); /* Get the migrated stack in normal memory */ - stack_base = (u32)get_bootloader_tmp_mem(hob_list, &stack_len); - ASSERT(stack_base != 0); + stack_base = (u32)fsp_get_bootloader_tmp_mem(hob_list, &stack_len); + assert(stack_base != 0); stack_top = stack_base + stack_len - sizeof(u32); /* * Old stack base is stored at the very end of the stack top, * use it to calculate the migrated shared data base */ - shared_data = (struct shared_data_t *)(stack_base + + shared_data = (struct shared_data *)(stack_base + ((u32)shared_data - *(u32 *)stack_top)); /* The boot loader main function entry */ @@ -127,50 +115,50 @@ void fsp_continue(struct shared_data_t *shared_data, u32 status, void *hob_list) void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) { - struct shared_data_t shared_data; + struct shared_data shared_data; fsp_init_f init; - struct fsp_init_params_t params; - struct fspinit_rtbuf_t rt_buf; - struct vpd_region_t *fsp_vpd; - struct fsp_header_t *fsp_hdr; - struct fsp_init_params_t *params_ptr; - struct upd_region_t *fsp_upd; - - fsp_hdr = (struct fsp_header_t *)find_fsp_header(); + struct fsp_init_params params; + struct fspinit_rtbuf rt_buf; + struct vpd_region *fsp_vpd; + struct fsp_header *fsp_hdr; + struct fsp_init_params *params_ptr; + struct upd_region *fsp_upd; + + fsp_hdr = (struct fsp_header *)find_fsp_header(); if (fsp_hdr == NULL) { /* No valid FSP info header was found */ - ASSERT(FALSE); + panic("Invalid FSP header"); } - fsp_upd = (struct upd_region_t *)&shared_data.fsp_upd; - memset((void *)&rt_buf, 0, sizeof(struct fspinit_rtbuf_t)); + fsp_upd = (struct upd_region *)&shared_data.fsp_upd; + memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf)); /* Reserve a gap in stack top */ rt_buf.common.stack_top = (u32 *)stack_top - 32; rt_buf.common.boot_mode = boot_mode; - rt_buf.common.upd_data = (struct upd_region_t *)fsp_upd; + rt_buf.common.upd_data = (struct upd_region *)fsp_upd; /* Get VPD region start */ - fsp_vpd = (struct vpd_region_t *)(fsp_hdr->img_base + + fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base + fsp_hdr->cfg_region_off); /* Verifify the VPD data region is valid */ - ASSERT((fsp_vpd->img_rev == VPD_IMAGE_REV) && + assert((fsp_vpd->img_rev == VPD_IMAGE_REV) && (fsp_vpd->sign == VPD_IMAGE_ID)); /* Copy default data from Flash */ memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset), - sizeof(struct upd_region_t)); + sizeof(struct upd_region)); /* Verifify the UPD data region is valid */ - ASSERT(fsp_upd->terminator == 0x55AA); + assert(fsp_upd->terminator == UPD_TERMINATOR); /* Override any UPD setting if required */ update_fsp_upd(fsp_upd); - memset((void *)¶ms, 0, sizeof(struct fsp_init_params_t)); + memset(¶ms, 0, sizeof(struct fsp_init_params)); params.nvs_buf = nvs_buf; - params.rt_buf = (struct fspinit_rtbuf_t *)&rt_buf; + params.rt_buf = (struct fspinit_rtbuf *)&rt_buf; params.continuation = (fsp_continuation_f)asm_continuation; init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init); @@ -199,32 +187,28 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) /* * Should never get here. - * Control will continue from romstage_main_continue_asm. + * Control will continue from fsp_continue. * This line below is to prevent the compiler from optimizing * structure intialization. + * + * DO NOT REMOVE! */ init(¶ms); - - /* - * Should never return. - * Control will continue from ContinuationFunc - */ - ASSERT(FALSE); } -u32 fsp_notify(struct fsp_header_t *fsp_hdr, u32 phase) +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) { fsp_notify_f notify; - struct fsp_notify_params_t params; - struct fsp_notify_params_t *params_ptr; + struct fsp_notify_params params; + struct fsp_notify_params *params_ptr; u32 status; if (!fsp_hdr) - fsp_hdr = (struct fsp_header_t *)find_fsp_header(); + fsp_hdr = (struct fsp_header *)find_fsp_header(); if (fsp_hdr == NULL) { /* No valid FSP info header */ - ASSERT(FALSE); + panic("Invalid FSP header"); } notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify); @@ -245,9 +229,9 @@ u32 fsp_notify(struct fsp_header_t *fsp_hdr, u32 phase) return status; } -u32 get_usable_lowmem_top(const void *hob_list) +u32 fsp_get_usable_lowmem_top(const void *hob_list) { - union hob_pointers_t hob; + union hob_pointers hob; phys_addr_t phys_start; u32 top; @@ -255,26 +239,26 @@ u32 get_usable_lowmem_top(const void *hob_list) hob.raw = (void *)hob_list; /* * Collect memory ranges */ - top = 0x100000; - while (!END_OF_HOB(hob)) { - if (hob.hdr->type == HOB_TYPE_RES_DESC) { + top = FSP_LOWMEM_BASE; + while (!end_of_hob(hob)) { + if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { if (hob.res_desc->type == RES_SYS_MEM) { phys_start = hob.res_desc->phys_start; /* Need memory above 1MB to be collected here */ - if (phys_start >= 0x100000 && - phys_start < (phys_addr_t)0x100000000) + if (phys_start >= FSP_LOWMEM_BASE && + phys_start < (phys_addr_t)FSP_HIGHMEM_BASE) top += (u32)(hob.res_desc->len); } } - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); } return top; } -u64 get_usable_highmem_top(const void *hob_list) +u64 fsp_get_usable_highmem_top(const void *hob_list) { - union hob_pointers_t hob; + union hob_pointers hob; phys_addr_t phys_start; u64 top; @@ -282,33 +266,33 @@ u64 get_usable_highmem_top(const void *hob_list) hob.raw = (void *)hob_list; /* Collect memory ranges */ - top = 0x100000000; - while (!END_OF_HOB(hob)) { - if (hob.hdr->type == HOB_TYPE_RES_DESC) { + top = FSP_HIGHMEM_BASE; + while (!end_of_hob(hob)) { + if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { if (hob.res_desc->type == RES_SYS_MEM) { phys_start = hob.res_desc->phys_start; /* Need memory above 1MB to be collected here */ - if (phys_start >= (phys_addr_t)0x100000000) + if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) top += (u32)(hob.res_desc->len); } } - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); } return top; } -u64 get_fsp_reserved_mem_from_guid(const void *hob_list, u64 *len, - struct efi_guid_t *guid) +u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, + struct efi_guid *guid) { - union hob_pointers_t hob; + union hob_pointers hob; /* Get the HOB list for processing */ hob.raw = (void *)hob_list; /* Collect memory ranges */ - while (!END_OF_HOB(hob)) { - if (hob.hdr->type == HOB_TYPE_RES_DESC) { + while (!end_of_hob(hob)) { + if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { if (hob.res_desc->type == RES_MEM_RESERVED) { if (compare_guid(&hob.res_desc->owner, guid)) { if (len) @@ -318,99 +302,100 @@ u64 get_fsp_reserved_mem_from_guid(const void *hob_list, u64 *len, } } } - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); } return 0; } -u32 get_fsp_reserved_mem(const void *hob_list, u32 *len) +u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) { - const struct efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; + const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; u64 length; u32 base; - base = (u32)get_fsp_reserved_mem_from_guid(hob_list, - &length, (struct efi_guid_t *)&guid); + base = (u32)fsp_get_reserved_mem_from_guid(hob_list, + &length, (struct efi_guid *)&guid); if ((len != 0) && (base != 0)) *len = (u32)length; return base; } -u32 get_tseg_reserved_mem(const void *hob_list, u32 *len) +u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) { - const struct efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; + const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; u64 length; u32 base; - base = (u32)get_fsp_reserved_mem_from_guid(hob_list, - &length, (struct efi_guid_t *)&guid); + base = (u32)fsp_get_reserved_mem_from_guid(hob_list, + &length, (struct efi_guid *)&guid); if ((len != 0) && (base != 0)) *len = (u32)length; return base; } -void *get_next_hob(u16 type, const void *hob_list) +void *fsp_get_next_hob(u16 type, const void *hob_list) { - union hob_pointers_t hob; + union hob_pointers hob; - ASSERT(hob_list != NULL); + assert(hob_list != NULL); hob.raw = (u8 *)hob_list; /* Parse the HOB list until end of list or matching type is found */ - while (!END_OF_HOB(hob)) { - if (hob.hdr->type == type) + while (!end_of_hob(hob)) { + if (get_hob_type(hob) == type) return hob.raw; - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); } return NULL; } -void *get_next_guid_hob(const struct efi_guid_t *guid, const void *hob_list) +void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list) { - union hob_pointers_t hob; + union hob_pointers hob; hob.raw = (u8 *)hob_list; - while ((hob.raw = get_next_hob(HOB_TYPE_GUID_EXT, + while ((hob.raw = fsp_get_next_hob(HOB_TYPE_GUID_EXT, hob.raw)) != NULL) { if (compare_guid(guid, &hob.guid->name)) break; - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); } return hob.raw; } -void *get_guid_hob_data(const void *hob_list, u32 *len, struct efi_guid_t *guid) +void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, + struct efi_guid *guid) { u8 *guid_hob; - guid_hob = get_next_guid_hob(guid, hob_list); + guid_hob = fsp_get_next_guid_hob(guid, hob_list); if (guid_hob == NULL) { return NULL; } else { if (len) - *len = GET_GUID_HOB_DATA_SIZE(guid_hob); + *len = get_guid_hob_data_size(guid_hob); - return GET_GUID_HOB_DATA(guid_hob); + return get_guid_hob_data(guid_hob); } } -void *get_fsp_nvs_data(const void *hob_list, u32 *len) +void *fsp_get_nvs_data(const void *hob_list, u32 *len) { - const struct efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; + const struct efi_guid guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; - return get_guid_hob_data(hob_list, len, (struct efi_guid_t *)&guid); + return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid); } -void *get_bootloader_tmp_mem(const void *hob_list, u32 *len) +void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) { - const struct efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; + const struct efi_guid guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; - return get_guid_hob_data(hob_list, len, (struct efi_guid_t *)&guid); + return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid); } diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c index dbc17102da..8e97c9b82a 100644 --- a/arch/x86/cpu/queensbay/tnc_dram.c +++ b/arch/x86/cpu/queensbay/tnc_dram.c @@ -14,17 +14,17 @@ DECLARE_GLOBAL_DATA_PTR; int dram_init(void) { phys_size_t ram_size = 0; - union hob_pointers_t hob; + union hob_pointers hob; hob.raw = gd->arch.hob_list; - while (!END_OF_HOB(hob)) { - if (hob.hdr->type == HOB_TYPE_RES_DESC) { + while (!end_of_hob(hob)) { + if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { if (hob.res_desc->type == RES_SYS_MEM || hob.res_desc->type == RES_MEM_RESERVED) { ram_size += hob.res_desc->len; } } - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); } gd->ram_size = ram_size; @@ -49,19 +49,19 @@ void dram_init_banksize(void) */ ulong board_get_usable_ram_top(ulong total_size) { - return get_usable_lowmem_top(gd->arch.hob_list); + return fsp_get_usable_lowmem_top(gd->arch.hob_list); } unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) { unsigned num_entries = 0; - union hob_pointers_t hob; + union hob_pointers hob; hob.raw = gd->arch.hob_list; - while (!END_OF_HOB(hob)) { - if (hob.hdr->type == HOB_TYPE_RES_DESC) { + while (!end_of_hob(hob)) { + if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { entries[num_entries].addr = hob.res_desc->phys_start; entries[num_entries].size = hob.res_desc->len; @@ -70,7 +70,7 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) else if (hob.res_desc->type == RES_MEM_RESERVED) entries[num_entries].type = E820_RESERVED; } - hob.raw = GET_NEXT_HOB(hob); + hob.raw = get_next_hob(hob); num_entries++; } -- cgit