
Hi BIn,
On Tue, 19 Nov 2019 at 00:25, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Oct 21, 2019 at 11:40 AM Simon Glass sjg@chromium.org wrote:
Add support for some important configuration options and FSP memory init. The memory init uses swizzle tables from the device tree.
Support for the FSP_S binary is also included.
Bootstage timing is used for both FSP_M and FSP_M and memory-mapped SPI
FSP_T and FSP_M ?
Will fix
reads.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3:
- Add a proper implementation of fsp_notify
- Add an fsp: tag
- Add bootstage timing for memory-mapped reads
- Add fsp_locate_fsp to locate an fsp component
- Add fspm_done() hook
- Add support for FSP-S component and VBT
- Simplify types for fsp_locate_fsp()
- Switch mmap to use SPI instead of SPI flash
Changes in v2: None
arch/x86/Kconfig | 61 ++++++++- arch/x86/include/asm/fsp2/fsp_api.h | 60 +++++++++ arch/x86/include/asm/fsp2/fsp_internal.h | 97 ++++++++++++++ arch/x86/lib/fsp2/Makefile | 10 ++ arch/x86/lib/fsp2/fsp_common.c | 13 ++ arch/x86/lib/fsp2/fsp_dram.c | 77 +++++++++++ arch/x86/lib/fsp2/fsp_init.c | 157 +++++++++++++++++++++++ arch/x86/lib/fsp2/fsp_meminit.c | 97 ++++++++++++++ arch/x86/lib/fsp2/fsp_silicon_init.c | 52 ++++++++ arch/x86/lib/fsp2/fsp_support.c | 129 +++++++++++++++++++ include/bootstage.h | 3 + 11 files changed, 754 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/fsp2/fsp_api.h create mode 100644 arch/x86/include/asm/fsp2/fsp_internal.h create mode 100644 arch/x86/lib/fsp2/Makefile create mode 100644 arch/x86/lib/fsp2/fsp_common.c create mode 100644 arch/x86/lib/fsp2/fsp_dram.c create mode 100644 arch/x86/lib/fsp2/fsp_init.c create mode 100644 arch/x86/lib/fsp2/fsp_meminit.c create mode 100644 arch/x86/lib/fsp2/fsp_silicon_init.c create mode 100644 arch/x86/lib/fsp2/fsp_support.c
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 17a6fe6d3d9..cbd3fc4f581 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -326,7 +326,7 @@ config X86_RAMTEST
config FLASH_DESCRIPTOR_FILE string "Flash descriptor binary filename"
depends on HAVE_INTEL_ME
depends on HAVE_INTEL_ME || FSP_VERSION2 default "descriptor.bin" help The filename of the file to use as flash descriptor in the
@@ -411,6 +411,63 @@ config FSP_ADDR The default base address of 0xfffc0000 indicates that the binary must be located at offset 0xc0000 from the beginning of a 1MB flash device.
+if FSP_VERSION2
+config FSP_FILE_T
string "Firmware-Support-Package binary filename (Temp RAM)"
default "fsp_t.bin"
help
The filename of the file to use for the temporary-RAM init phase from
the Firmware-Support-Package binary. Put this in the board directory.
It is used to set up an initial area of RAM which can be used for the
stack and other purposes, while bringing up the main system DRAM.
+config FSP_ADDR_T
hex "Firmware-Support-Package binary location (Temp RAM)"
default 0xffff8000
help
FSP is not Position-Independent Code (PIC) and FSP components have to
be rebased if 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.
+config FSP_FILE_M
string "Firmware-Support-Package binary filename (Memory Init)"
default "fsp_m.bin"
help
The filename of the file to use for the RAM init phase from the
Firmware Support Package binary. Put this in the board directory.
It is used to set up the main system DRAM and runs in SPL, once
temporary RAM (CAR) is working.
+config FSP_FILE_S
string "Firmware-Support-Package binary filename (Silicon Init)"
default "fsp_s.bin"
help
The filename of the file to use for the Silicon init phase from the
Firmware Support Package binary. Put this in the board directory.
It is used to set up the silicon to work correctly and must be
executed after DRAM is running.
+config FSP_FILE_VBT
There is already a VBT_FILE config option for this.
Oops, will drop.
One issue here is that we are using hard-coded positions for things that don't need to be in a fixed place (I think). It makes it harder to avoid image overlays.
Now that we have a way to read symbols from binman, perhaps some of the addresses should be left out? Then binman can pack them automatically.
string "Firmware-Support-Package Video BIOS Table (VBT)"
default "vbt.bin"
help
The filename of the file to use for the video data needd by the
Silicon init phase from the Firmware Support Package binary. Put this
in the board directory. It is used to set up the video parameters so
that the display can be used.
+config IFWI_INPUT_FILE
string "Filename containing FIT (Firmware Interface Table) with IFWI"
default "fitimage.bin"
help
The IFWI is obtained by running a tool on this file to extract the
IFWI. Put this in the board directory. The IFWI contains U-Boot TPL,
microcode and other internal items.
+endif
config FSP_TEMP_RAM_ADDR hex depends on FSP_VERSION1 @@ -629,7 +686,7 @@ config VBT_ADDR
config VIDEO_FSP bool "Enable FSP framebuffer driver support"
depends on HAVE_VBT && DM_VIDEO
depends on (HAVE_VBT || FSP_VERSION2) && DM_VIDEO help Turn on this option to enable a framebuffer driver when U-Boot is using Video BIOS Table (VBT) image for FSP firmware to initialize
diff --git a/arch/x86/include/asm/fsp2/fsp_api.h b/arch/x86/include/asm/fsp2/fsp_api.h new file mode 100644 index 00000000000..93b6472dce0 --- /dev/null +++ b/arch/x86/include/asm/fsp2/fsp_api.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: Intel */ +/*
- Copyright (C) 2015-2016 Intel Corp.
- (Written by Andrey Petrov andrey.petrov@intel.com for Intel Corp.)
- (Written by Alexandru Gagniuc alexandrux.gagniuc@intel.com for Intel Corp.)
- Mostly taken from coreboot fsp2_0/memory_init.c
- */
+#ifndef __ASM_FSP2_API_H +#define __ASM_FSP2_API_H
+#include <asm/fsp/fsp_api.h>
+struct fspm_upd; +struct fsps_upd; +struct hob_header;
+enum fsp_boot_mode {
FSP_BOOT_WITH_FULL_CONFIGURATION = 0x00,
FSP_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01,
FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02,
FSP_BOOT_ON_S4_RESUME = 0x05,
FSP_BOOT_ON_S3_RESUME = 0x11,
FSP_BOOT_ON_FLASH_UPDATE = 0x12,
FSP_BOOT_IN_RECOVERY_MODE = 0x20
+};
+struct __packed fsp_upd_header {
u64 signature;
u8 revision;
u8 reserved[23];
+};
+/**
- fsp_memory_init() - Init the SDRAM
- @s3wake: true if we are booting from resume, so cannot reinit the mememory
from scatch since we will lose its contents
- @use_spi_flash: true to use the fast SPI driver to read FSP, otherwise use
mapped SPI
- @return 0 if OK, -ve on error
- */
+int fsp_memory_init(bool s3wake, bool use_spi_flash);
+typedef asmlinkage int (*fsp_memory_init_func)(struct fspm_upd *params,
struct hob_header **hobp);
+/**
- fsp_silicon_init() - Init the silicon
- This calls the FSP's 'silicon init' entry point
- @s3wake: true if we are booting from resume
Should have the same descriptions as fsp_memory_init()
- @return 0 if OK, -ve on error
- */
+int fsp_silicon_init(bool s3wake, bool use_spi_flash);
+typedef asmlinkage int (*fsp_silicon_init_func)(struct fsps_upd *params);
+#endif diff --git a/arch/x86/include/asm/fsp2/fsp_internal.h b/arch/x86/include/asm/fsp2/fsp_internal.h new file mode 100644 index 00000000000..5893f1ffcc7 --- /dev/null +++ b/arch/x86/include/asm/fsp2/fsp_internal.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: Intel */ +/*
- Copyright (C) 2015-2016 Intel Corp.
- (Written by Alexandru Gagniuc alexandrux.gagniuc@intel.com for Intel Corp.)
- Mostly taken from coreboot
- */
+#ifndef __ASM_FSP_INTERNAL_H +#define __ASM_FSP_INTERNAL_H
+struct binman_entry; +struct fsp_header; +struct fspm_upd; +struct fsps_upd;
+enum fsp_type_t {
FSP_M,
FSP_S,
+};
+int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
struct fsp_header **fspp);
+/**
- fsp_locate_fsp() - Locate an FSP component
- This finds an FSP component by various methods. It is not as general-purpose
- as it looks, since it expects FSP-M to be requested in SPL (only), and FSP-S
- to be requested in U-Boot proper.
- @type: Component to locate
- @entry: Returns location of component
- @use_spi_flash: true to read using the Fast SPI driver, false to use
memory-mapped SPI flash
- @devp: Returns northbridge device
- @hdrp: Returns FSP header
- @rom_offsetp: If non-NULL, returns the offset to add to any image position to
find the memory-mapped location of that position. For example, for ROM
position 0x1000, it will be mapped into 0x1000 + *rom_offsetp.
- */
+int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
bool use_spi_flash, struct udevice **devp,
struct fsp_header **hdrp, ulong *rom_offsetp);
+/**
- arch_fsp_s_preinit() - Perform init needed before calling FSP-S
Considering other routines in this file are having fspm_ as the prefix, should we name this function to arch_fsps_preinit()?
Will do.
Or rename others to fsp_m_ as the prefix?
- This allows use of probed drivers and PCI so is a convenient place to do any
- init that is needed before FSP-S is called. After this, U-Boot relocates and
- calls arch_fsp_init_r() before PCI is probed, and that function is not
- allowed to probe PCI before calling FSP-S.
- */
+int arch_fsp_s_preinit(void);
+/**
- fspm_update_config() - Set up the config structure for FSP-M
- @dev: Hostbridge device containing config
- @upd: Config data to fill in
- @return 0 if OK, -ve on error
- */
+int fspm_update_config(struct udevice *dev, struct fspm_upd *upd);
+/**
- fspm_done() - Indicate that memory init is complete
- This allows the board to do whatever post-init it needs before things
- continue.
- @dev: Hostbridge device
- @return 0 if OK, -ve on error
- */
+int fspm_done(struct udevice *dev);
+/**
- fsps_update_config() - Set up the config structure for FSP-S
- @dev: Hostbridge device containing config
- @rom_offset: Value to add to convert from ROM offset to memory-mapped address
- @upd: Config data to fill in
- @return 0 if OK, -ve on error
- */
+int fsps_update_config(struct udevice *dev, ulong rom_offset,
struct fsps_upd *upd);
+/**
- prepare_mrc_cache() - Read the MRC cache into the product-data struct
- This looks for cached Memory-reference code (MRC) data and stores it into
- @upd for use by the FSP-M binary.
- @return 0 if OK, -ENOENT if no data (whereupon the caller can continue and
expect a slower boot), other -ve value on other error
- */
+int prepare_mrc_cache(struct fspm_upd *upd);
+#endif diff --git a/arch/x86/lib/fsp2/Makefile b/arch/x86/lib/fsp2/Makefile new file mode 100644 index 00000000000..ddbe2d0db26 --- /dev/null +++ b/arch/x86/lib/fsp2/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2019 Google LLC
+obj-y += fsp_common.o +obj-y += fsp_dram.o +obj-y += fsp_init.o +obj-y += fsp_meminit.o +obj-y += fsp_silicon_init.o +obj-y += fsp_support.o diff --git a/arch/x86/lib/fsp2/fsp_common.c b/arch/x86/lib/fsp2/fsp_common.c new file mode 100644 index 00000000000..f69456e43a2 --- /dev/null +++ b/arch/x86/lib/fsp2/fsp_common.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2019 Google LLC
- Written by Simon Glass sjg@chromium.org
- */
+#include <common.h> +#include <init.h>
+int arch_fsp_init(void) +{
return 0;
+} diff --git a/arch/x86/lib/fsp2/fsp_dram.c b/arch/x86/lib/fsp2/fsp_dram.c new file mode 100644 index 00000000000..a3f95d0cf96 --- /dev/null +++ b/arch/x86/lib/fsp2/fsp_dram.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2019 Google LLC
- Written by Simon Glass sjg@chromium.org
- */
+#include <common.h> +#include <acpi_s3.h> +#include <handoff.h> +#include <spl.h> +#include <asm/arch/cpu.h> +#include <asm/fsp/fsp_support.h> +#include <asm/fsp2/fsp_api.h> +#include <asm/fsp2/fsp_internal.h>
+int dram_init(void) +{
int ret;
if (spl_phase() == PHASE_SPL) {
+#ifdef CONFIG_HAVE_ACPI_RESUME
bool s3wake = gd->arch.prev_sleep_state == ACPI_S3;
+#else
bool s3wake = false;
+#endif
ret = fsp_memory_init(s3wake, BOOT_FROM_FAST_SPI_FLASH);
if (ret) {
debug("Memory init failed (err=%x)\n", ret);
return ret;
}
/* The FSP has already set up DRAM, so grab the info we need */
ret = fsp_scan_for_ram_size();
if (ret)
return ret;
+#ifdef CONFIG_ENABLE_MRC_CACHE
gd->arch.mrc[MRC_TYPE_NORMAL].buf =
fsp_get_nvs_data(gd->arch.hob_list,
&gd->arch.mrc[MRC_TYPE_NORMAL].len);
gd->arch.mrc[MRC_TYPE_VAR].buf =
fsp_get_var_nvs_data(gd->arch.hob_list,
&gd->arch.mrc[MRC_TYPE_VAR].len);
log_debug("normal %x, var %x\n",
gd->arch.mrc[MRC_TYPE_NORMAL].len,
gd->arch.mrc[MRC_TYPE_VAR].len);
+#endif
} else {
+#if CONFIG_IS_ENABLED(HANDOFF)
struct spl_handoff *ho = gd->spl_handoff;
if (!ho) {
debug("No SPL handoff found\n");
return -ESTRPIPE;
}
gd->ram_size = ho->ram_size;
handoff_load_dram_banks(ho);
+#endif
ret = arch_fsp_s_preinit();
if (ret)
return log_msg_ret("fsp_s_preinit", ret);
}
return 0;
+}
+ulong board_get_usable_ram_top(ulong total_size) +{ +#if CONFIG_IS_ENABLED(HANDOFF)
struct spl_handoff *ho = gd->spl_handoff;
return ho->arch.usable_ram_top;
+#endif
return gd->ram_top;
+} diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c new file mode 100644 index 00000000000..111eb51d34b --- /dev/null +++ b/arch/x86/lib/fsp2/fsp_init.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright 2019 Google LLC
- */
+#include <common.h> +#include <binman.h> +#include <binman_sym.h> +#include <cbfs.h> +#include <dm.h> +#include <init.h> +#include <spi.h> +#include <spl.h> +#include <spi_flash.h> +#include <asm/arch/gpio.h> +#include <dm/uclass-internal.h> +#include <asm/fsp2/fsp_internal.h>
+int arch_cpu_init_dm(void) +{
struct udevice *dev;
ofnode node;
int ret;
if (spl_phase() != PHASE_BOARD_F)
return 0;
/* Probe all GPIO devices to set up the pads */
ret = uclass_first_device_err(UCLASS_GPIO, &dev);
Why is this GPIO probe needed in the generic FSP support?
This is for pinctrl, to set up the pads. With v4 I am converting this to use pinctrl so it should be a little bit clearer. We need to set up the pins early on, before calling FSP-S.
I think every board will need to do this, so I think it makes sense to use generate code. What do you think?
if (ret)
return log_msg_ret("no fsp GPIO", ret);
node = ofnode_path("fsp");
if (!ofnode_valid(node))
return log_msg_ret("no fsp params", -EINVAL);
ret = hostbridge_config_pads_for_node(dev, node);
if (ret)
return log_msg_ret("pad config", ret);
return ret;
+}
+#if !defined(CONFIG_TPL_BUILD) +binman_sym_declare(ulong, intel_fsp_m, image_pos); +binman_sym_declare(ulong, intel_fsp_m, size);
+static int get_coreboot_fsp(enum fsp_type_t type, ulong map_base,
get_uboot_fsp?
Should be cbfs I'll add a comment as this is mostly for development.
struct binman_entry *entry)
+{
/* Hard-coded position of CBFS in ROM */
Why hard-coded?
Just because this is for development and it doesn't seem worth adding code to read the FMAP. Will add a comment.
ulong cbfs_base = 0x205000;
ulong cbfs_size = 0x1bb000;
struct cbfs_priv *cbfs;
int ret;
ret = cbfs_init_mem(map_base + cbfs_base, cbfs_size, &cbfs);
if (ret)
return ret;
if (!ret) {
const struct cbfs_cachenode *node;
node = cbfs_find_file(cbfs, "fspm.bin");
if (!node)
return log_msg_ret("fspm node", -ENOENT);
entry->image_pos = (ulong)node->data;
entry->size = node->data_length;
}
return 0;
+}
+int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry,
bool use_spi_flash, struct udevice **devp,
struct fsp_header **hdrp, ulong *rom_offsetp)
+{
ulong mask = CONFIG_ROM_SIZE - 1;
struct udevice *dev;
ulong rom_offset = 0;
uint map_size;
ulong map_base;
uint offset;
int ret;
/*
* Find the devices but don't probe them, since we don't want to
* auto-config PCI before silicon init runs
*/
ret = uclass_find_first_device(UCLASS_NORTHBRIDGE, &dev);
if (ret)
return log_msg_ret("Cannot get northbridge", ret);
if (!use_spi_flash) {
struct udevice *sf;
/* Just use the SPI driver to get the memory map */
ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf);
if (ret)
return log_msg_ret("Cannot get SPI flash", ret);
ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset);
if (ret)
return log_msg_ret("Could not get flash mmap", ret);
}
if (spl_phase() >= PHASE_BOARD_F) {
if (type != FSP_S)
return -EPROTONOSUPPORT;
ret = binman_entry_find("intel-fsp-s", entry);
if (ret)
return log_msg_ret("binman entry", ret);
if (!use_spi_flash)
rom_offset = (map_base & mask) - CONFIG_ROM_SIZE;
} else {
ret = -ENOENT;
if (false)
/* Support using a hybrid image build by coreboot */
U-Boot?
No it is actually coreboot. It lets coreboot do the early stages so we can make sure U-Boot is doing the same things it should. See above.
[..]
+int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
struct fsp_header **fspp)
+{
static efi_guid_t guid = FSP_HEADER_GUID;
struct fv_ext_header *exhdr;
struct fsp_header *fsp;
struct ffs_file_header *file_hdr;
struct fv_header *fv;
struct raw_section *raw;
void *ptr, *base;
u8 buf[PROBE_BUF_SIZE];
struct udevice *dev;
int ret;
/* You are in a maze of twisty headers all alike */
What does this comment mean?
Web search it :-)
I'll expand the comment.
Regards, Simon