From 83311886151f80ef24d30f850baece07d08863cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:11 -0600 Subject: [PATCH 01/95] x86: Rename existing FSP code to fsp1 Since there is now a new version of the FSP and it is incompatible with the existing version, move the code into an fsp1 directory. This will allow us to put FSP v2 code into an fsp2 directory. Add a Kconfig which defines which version is in use. Some of the code in this new fsp1/ directory is generic across both FSPv1 and FSPv2. Future patches will address this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/Kconfig | 25 ++++++++++++++++++- arch/x86/cpu/baytrail/acpi.c | 2 +- arch/x86/cpu/baytrail/fsp_configs.c | 2 +- arch/x86/cpu/braswell/fsp_configs.c | 2 +- arch/x86/cpu/ivybridge/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/tnc.c | 2 +- arch/x86/include/asm/{fsp => fsp1}/fsp_api.h | 0 .../include/asm/{fsp => fsp1}/fsp_azalia.h | 0 .../include/asm/{fsp => fsp1}/fsp_bootmode.h | 0 arch/x86/include/asm/{fsp => fsp1}/fsp_ffs.h | 0 arch/x86/include/asm/{fsp => fsp1}/fsp_fv.h | 0 arch/x86/include/asm/{fsp => fsp1}/fsp_hob.h | 0 .../asm/{fsp => fsp1}/fsp_infoheader.h | 0 .../include/asm/{fsp => fsp1}/fsp_support.h | 0 .../x86/include/asm/{fsp => fsp1}/fsp_types.h | 0 arch/x86/include/asm/u-boot-x86.h | 2 +- arch/x86/lib/Makefile | 3 ++- arch/x86/lib/{fsp => fsp1}/Makefile | 0 arch/x86/lib/{fsp => fsp1}/fsp_car.S | 0 arch/x86/lib/{fsp => fsp1}/fsp_common.c | 2 +- arch/x86/lib/{fsp => fsp1}/fsp_dram.c | 2 +- arch/x86/lib/{fsp => fsp1}/fsp_graphics.c | 2 +- arch/x86/lib/{fsp => fsp1}/fsp_support.c | 2 +- .../som-db5800-som-6867/som-db5800-som-6867.c | 2 +- board/intel/cherryhill/cherryhill.c | 2 +- cmd/x86/fsp.c | 2 +- drivers/pci/pci-uclass.c | 2 +- 28 files changed, 41 insertions(+), 17 deletions(-) rename arch/x86/include/asm/{fsp => fsp1}/fsp_api.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_azalia.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_bootmode.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_ffs.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_fv.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_hob.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_infoheader.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_support.h (100%) rename arch/x86/include/asm/{fsp => fsp1}/fsp_types.h (100%) rename arch/x86/lib/{fsp => fsp1}/Makefile (100%) rename arch/x86/lib/{fsp => fsp1}/fsp_car.S (100%) rename arch/x86/lib/{fsp => fsp1}/fsp_common.c (99%) rename arch/x86/lib/{fsp => fsp1}/fsp_dram.c (98%) rename arch/x86/lib/{fsp => fsp1}/fsp_graphics.c (98%) rename arch/x86/lib/{fsp => fsp1}/fsp_support.c (99%) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 218e817cf3..314f8def7a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -364,6 +364,29 @@ config HAVE_FSP Note: Without this binary U-Boot will not be able to set up its SDRAM so will not boot. +choice + prompt "FSP version" + depends on HAVE_FSP + default FSP_VERSION1 + help + Selects the FSP version to use. Intel has published several versions + of the FSP External Architecture Specification and this allows + selection of the version number used by a particular SoC. + +config FSP_VERSION1 + bool "FSP version 1.x" + help + This covers versions 1.0 and 1.1a. See here for details: + https://github.com/IntelFsp/fsp/wiki + +config FSP_VERSION2 + bool "FSP version 2.x" + help + This covers versions 2.0 and 2.1. See here for details: + https://github.com/IntelFsp/fsp/wiki + +endchoice + config FSP_FILE string "Firmware Support Package binary filename" depends on HAVE_FSP @@ -429,7 +452,7 @@ config ENABLE_MRC_CACHE For platforms that use Intel FSP for the memory initialization, please check FSP output HOB via U-Boot command 'fsp hob' to see - if there is FSP_NON_VOLATILE_STORAGE_HOB_GUID (asm/fsp/fsp_hob.h). + if there is FSP_NON_VOLATILE_STORAGE_HOB_GUID (asm/fsp1/fsp_hob.h). If such GUID does not exist, MRC cache is not available on such platform (eg: Intel Queensbay), which means selecting this option here does not make any difference. diff --git a/arch/x86/cpu/baytrail/acpi.c b/arch/x86/cpu/baytrail/acpi.c index 445e4ba2d7..1e3829a433 100644 --- a/arch/x86/cpu/baytrail/acpi.c +++ b/arch/x86/cpu/baytrail/acpi.c @@ -167,7 +167,7 @@ void acpi_create_gnvs(struct acpi_global_nvs *gnvs) * and PMC_BASE_ADDRESS are accessed, so we need make sure the base addresses * of these two blocks are programmed by either U-Boot or FSP. * - * It has been verified that 1st phase API (see arch/x86/lib/fsp/fsp_car.S) + * It has been verified that 1st phase API (see arch/x86/lib/fsp1/fsp_car.S) * on Intel BayTrail SoC already initializes these two base addresses so * we are safe to access these registers here. */ diff --git a/arch/x86/cpu/baytrail/fsp_configs.c b/arch/x86/cpu/baytrail/fsp_configs.c index cefd26299a..5b5d66aa5e 100644 --- a/arch/x86/cpu/baytrail/fsp_configs.c +++ b/arch/x86/cpu/baytrail/fsp_configs.c @@ -7,7 +7,7 @@ #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/braswell/fsp_configs.c b/arch/x86/cpu/braswell/fsp_configs.c index 7fe6fa7995..607e333f21 100644 --- a/arch/x86/cpu/braswell/fsp_configs.c +++ b/arch/x86/cpu/braswell/fsp_configs.c @@ -5,7 +5,7 @@ #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/ivybridge/fsp_configs.c b/arch/x86/cpu/ivybridge/fsp_configs.c index 2fd06b3bed..773c2b2a0a 100644 --- a/arch/x86/cpu/ivybridge/fsp_configs.c +++ b/arch/x86/cpu/ivybridge/fsp_configs.c @@ -5,7 +5,7 @@ #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c index c4d117783c..0dd1901e07 100644 --- a/arch/x86/cpu/queensbay/fsp_configs.c +++ b/arch/x86/cpu/queensbay/fsp_configs.c @@ -5,7 +5,7 @@ */ #include -#include +#include void update_fsp_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index 76556fc7f7..66737e655b 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include static int __maybe_unused disable_igd(void) diff --git a/arch/x86/include/asm/fsp/fsp_api.h b/arch/x86/include/asm/fsp1/fsp_api.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_api.h rename to arch/x86/include/asm/fsp1/fsp_api.h diff --git a/arch/x86/include/asm/fsp/fsp_azalia.h b/arch/x86/include/asm/fsp1/fsp_azalia.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_azalia.h rename to arch/x86/include/asm/fsp1/fsp_azalia.h diff --git a/arch/x86/include/asm/fsp/fsp_bootmode.h b/arch/x86/include/asm/fsp1/fsp_bootmode.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_bootmode.h rename to arch/x86/include/asm/fsp1/fsp_bootmode.h diff --git a/arch/x86/include/asm/fsp/fsp_ffs.h b/arch/x86/include/asm/fsp1/fsp_ffs.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_ffs.h rename to arch/x86/include/asm/fsp1/fsp_ffs.h diff --git a/arch/x86/include/asm/fsp/fsp_fv.h b/arch/x86/include/asm/fsp1/fsp_fv.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_fv.h rename to arch/x86/include/asm/fsp1/fsp_fv.h diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp1/fsp_hob.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_hob.h rename to arch/x86/include/asm/fsp1/fsp_hob.h diff --git a/arch/x86/include/asm/fsp/fsp_infoheader.h b/arch/x86/include/asm/fsp1/fsp_infoheader.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_infoheader.h rename to arch/x86/include/asm/fsp1/fsp_infoheader.h diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_support.h rename to arch/x86/include/asm/fsp1/fsp_support.h diff --git a/arch/x86/include/asm/fsp/fsp_types.h b/arch/x86/include/asm/fsp1/fsp_types.h similarity index 100% rename from arch/x86/include/asm/fsp/fsp_types.h rename to arch/x86/include/asm/fsp1/fsp_types.h diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index c252192bf4..2466ad2ad3 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -74,7 +74,7 @@ u32 isa_map_rom(u32 bus_addr, int size); /* arch/x86/lib/... */ int video_bios_init(void); -/* arch/x86/lib/fsp/... */ +/* arch/x86/lib/fsp1,2/... */ /** * fsp_save_s3_stack() - save stack address to CMOS for next S3 boot diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 906be5eab9..a8c7448ee4 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -43,7 +43,8 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZBOOT) += zimage.o endif obj-$(CONFIG_USE_HOB) += hob.o -obj-$(CONFIG_HAVE_FSP) += fsp/ +obj-$(CONFIG_FSP_VERSION1) += fsp1/ +obj-$(CONFIG_FSP_VERSION2) += fsp2/ ifdef CONFIG_SPL_BUILD ifdef CONFIG_TPL_BUILD diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp1/Makefile similarity index 100% rename from arch/x86/lib/fsp/Makefile rename to arch/x86/lib/fsp1/Makefile diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp1/fsp_car.S similarity index 100% rename from arch/x86/lib/fsp/fsp_car.S rename to arch/x86/lib/fsp1/fsp_car.S diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c similarity index 99% rename from arch/x86/lib/fsp/fsp_common.c rename to arch/x86/lib/fsp1/fsp_common.c index ed0827c6e9..591eef7b81 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c similarity index 98% rename from arch/x86/lib/fsp/fsp_dram.c rename to arch/x86/lib/fsp1/fsp_dram.c index 3a23b70410..3bf65b495c 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp1/fsp_graphics.c similarity index 98% rename from arch/x86/lib/fsp/fsp_graphics.c rename to arch/x86/lib/fsp1/fsp_graphics.c index 91d2d08557..52e71334f9 100644 --- a/arch/x86/lib/fsp/fsp_graphics.c +++ b/arch/x86/lib/fsp1/fsp_graphics.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp1/fsp_support.c similarity index 99% rename from arch/x86/lib/fsp/fsp_support.c rename to arch/x86/lib/fsp1/fsp_support.c index 0eaa9b232b..019a42f53f 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp1/fsp_support.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void) diff --git a/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c b/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c index ac12f303a3..8f4c587371 100644 --- a/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c +++ b/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c @@ -5,7 +5,7 @@ */ #include -#include +#include /* ALC262 Verb Table - 10EC0262 */ static const u32 verb_table_data13[] = { diff --git a/board/intel/cherryhill/cherryhill.c b/board/intel/cherryhill/cherryhill.c index 695af6bb7e..c037d5b14c 100644 --- a/board/intel/cherryhill/cherryhill.c +++ b/board/intel/cherryhill/cherryhill.c @@ -5,7 +5,7 @@ #include #include -#include +#include static const struct gpio_family gpio_family[] = { GPIO_FAMILY_CONF("SOUTHEAST_2_hshvfamily_2x3_rcomp_7_0", NA, 0, diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c index efa183854b..fb27624422 100644 --- a/cmd/x86/fsp.c +++ b/cmd/x86/fsp.c @@ -5,7 +5,7 @@ #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index ab3e1310eb..b73d0cd70a 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -12,7 +12,7 @@ #include #include #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) -#include +#include #endif #include "pci_internal.h" From 6e93c64117bb8d04586bf095a8af75c25c2a7392 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:12 -0600 Subject: [PATCH 02/95] x86: Move fsp_azalia.h to the generic fsp directory This header file is the same for FSP v1 and v2. Move it into the general fsp directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: remove forward declarations in fsp_support.h] Signed-off-by: Bin Meng --- arch/x86/include/asm/{fsp1 => fsp}/fsp_azalia.h | 0 arch/x86/include/asm/fsp1/fsp_support.h | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) rename arch/x86/include/asm/{fsp1 => fsp}/fsp_azalia.h (100%) diff --git a/arch/x86/include/asm/fsp1/fsp_azalia.h b/arch/x86/include/asm/fsp/fsp_azalia.h similarity index 100% rename from arch/x86/include/asm/fsp1/fsp_azalia.h rename to arch/x86/include/asm/fsp/fsp_azalia.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 7b92392a27..b0c36a41fe 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -14,7 +14,7 @@ #include "fsp_api.h" #include "fsp_infoheader.h" #include "fsp_bootmode.h" -#include "fsp_azalia.h" +#include #include #include @@ -22,7 +22,6 @@ #define FSP_HIGHMEM_BASE 0x100000000ULL #define UPD_TERMINATOR 0x55AA - /** * FSP Continuation assembly helper routine * From 8cd29798d6a8e3cd3061ba855f6ea2b95ec47afc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:13 -0600 Subject: [PATCH 03/95] x86: Create a new fsp_arch.h header At present fsp_support.h includes fsp_vpd.h which is an FPSv1 concept (VPD means Vital Product Data). For FSPv2 only UPD (Updatable Product Data) is used. To avoid mangling header files, put these two includes in a separate header which we can adjust as necessary for FSPv2. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/fsp1/fsp_support.h | 3 +-- arch/x86/include/asm/fsp_arch.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/fsp_arch.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index b0c36a41fe..2fa6619c03 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -14,9 +14,8 @@ #include "fsp_api.h" #include "fsp_infoheader.h" #include "fsp_bootmode.h" +#include #include -#include -#include #define FSP_LOWMEM_BASE 0x100000UL #define FSP_HIGHMEM_BASE 0x100000000ULL diff --git a/arch/x86/include/asm/fsp_arch.h b/arch/x86/include/asm/fsp_arch.h new file mode 100644 index 0000000000..fb7f9109f7 --- /dev/null +++ b/arch/x86/include/asm/fsp_arch.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 Google LLC + * Written by Simon Glass + * + * Architecture-specific definitions (FSP config and VPD/UPD) + */ + +#ifndef __FSP_ARCH_H__ +#define __FSP_ARCH_H__ + +/* + * Note: use #ifndef __ASSEMBLY__ around any struct definitions or other C code + * since this file can be included from assembly. + */ + +#include +#include + +#endif From 8a0b4e2dd7ce8a93ef49bed916e96c569a95ff23 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:14 -0600 Subject: [PATCH 04/95] x86: Move fsp_api.h inclusion out of fsp_support.h This header file is different for each version of FSP. Move it into the fsp_arch.h header file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/fsp1/fsp_support.h | 1 - arch/x86/include/asm/fsp_arch.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 2fa6619c03..c75afe9356 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -11,7 +11,6 @@ #include "fsp_hob.h" #include "fsp_fv.h" #include "fsp_ffs.h" -#include "fsp_api.h" #include "fsp_infoheader.h" #include "fsp_bootmode.h" #include diff --git a/arch/x86/include/asm/fsp_arch.h b/arch/x86/include/asm/fsp_arch.h index fb7f9109f7..b223141c44 100644 --- a/arch/x86/include/asm/fsp_arch.h +++ b/arch/x86/include/asm/fsp_arch.h @@ -14,6 +14,7 @@ * since this file can be included from assembly. */ +#include #include #include From 2b5560a6bdafe4e1217938b8b772b8f545136dd8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:15 -0600 Subject: [PATCH 05/95] x86: Move fsp_types.h to the generic fsp directory This header file is the same for FSP v1 and v2. Move it into the general fsp directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/{fsp1 => fsp}/fsp_types.h | 0 arch/x86/include/asm/fsp1/fsp_support.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/include/asm/{fsp1 => fsp}/fsp_types.h (100%) diff --git a/arch/x86/include/asm/fsp1/fsp_types.h b/arch/x86/include/asm/fsp/fsp_types.h similarity index 100% rename from arch/x86/include/asm/fsp1/fsp_types.h rename to arch/x86/include/asm/fsp/fsp_types.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index c75afe9356..e5ec2af83e 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -7,7 +7,7 @@ #ifndef __FSP_SUPPORT_H__ #define __FSP_SUPPORT_H__ -#include "fsp_types.h" +#include #include "fsp_hob.h" #include "fsp_fv.h" #include "fsp_ffs.h" From aae5b4613a4b68efee33ac6803440ccc3a18ec55 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:16 -0600 Subject: [PATCH 06/95] x86: Move fsp_fv.h to the generic fsp directory This header file is the same for FSP v1 and v2. Move it into the general fsp directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/{fsp1 => fsp}/fsp_fv.h | 0 arch/x86/include/asm/fsp1/fsp_support.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/include/asm/{fsp1 => fsp}/fsp_fv.h (100%) diff --git a/arch/x86/include/asm/fsp1/fsp_fv.h b/arch/x86/include/asm/fsp/fsp_fv.h similarity index 100% rename from arch/x86/include/asm/fsp1/fsp_fv.h rename to arch/x86/include/asm/fsp/fsp_fv.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index e5ec2af83e..8376b2ad40 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -7,9 +7,9 @@ #ifndef __FSP_SUPPORT_H__ #define __FSP_SUPPORT_H__ +#include #include #include "fsp_hob.h" -#include "fsp_fv.h" #include "fsp_ffs.h" #include "fsp_infoheader.h" #include "fsp_bootmode.h" From e4499b52652cf2e13756d5b23b8d0118d5bf76d6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 2 Oct 2019 08:25:10 +0800 Subject: [PATCH 07/95] x86: Move fsp_hob.h to the generic fsp directory This header file is the same for FSP v1 and v2. Move it into the general fsp directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: remove inclusion of fsp_hob.h in fsp_support.h] Signed-off-by: Bin Meng --- arch/x86/include/asm/{fsp1 => fsp}/fsp_hob.h | 0 arch/x86/include/asm/fsp1/fsp_support.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/include/asm/{fsp1 => fsp}/fsp_hob.h (100%) diff --git a/arch/x86/include/asm/fsp1/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h similarity index 100% rename from arch/x86/include/asm/fsp1/fsp_hob.h rename to arch/x86/include/asm/fsp/fsp_hob.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 8376b2ad40..e204045482 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -8,8 +8,8 @@ #define __FSP_SUPPORT_H__ #include +#include #include -#include "fsp_hob.h" #include "fsp_ffs.h" #include "fsp_infoheader.h" #include "fsp_bootmode.h" From 21a1133d823b3cadbbe9f18475948bfcd587be60 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 2 Oct 2019 08:26:41 +0800 Subject: [PATCH 08/95] x86: Move fsp_infoheader.h to the generic fsp directory This header file is the same for FSP v1 and v2. Move it into the general fsp directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: move rename of fsp_infoheader.h from previous patch to this one] Signed-off-by: Bin Meng --- arch/x86/include/asm/{fsp1 => fsp}/fsp_infoheader.h | 0 arch/x86/include/asm/fsp1/fsp_support.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/include/asm/{fsp1 => fsp}/fsp_infoheader.h (100%) diff --git a/arch/x86/include/asm/fsp1/fsp_infoheader.h b/arch/x86/include/asm/fsp/fsp_infoheader.h similarity index 100% rename from arch/x86/include/asm/fsp1/fsp_infoheader.h rename to arch/x86/include/asm/fsp/fsp_infoheader.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index e204045482..ed4335ed29 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -9,9 +9,9 @@ #include #include +#include #include #include "fsp_ffs.h" -#include "fsp_infoheader.h" #include "fsp_bootmode.h" #include #include From 79b228baae06a57d0d01358e832d5ea2f2cc02d3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:19 -0600 Subject: [PATCH 09/95] x86: Move fsp_bootmode.h to the generic fsp directory This header file is the same for FSP v1 and v2, although there may be some additions to come. Move it into the generic fsp directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/{fsp1 => fsp}/fsp_bootmode.h | 0 arch/x86/include/asm/fsp1/fsp_support.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/include/asm/{fsp1 => fsp}/fsp_bootmode.h (100%) diff --git a/arch/x86/include/asm/fsp1/fsp_bootmode.h b/arch/x86/include/asm/fsp/fsp_bootmode.h similarity index 100% rename from arch/x86/include/asm/fsp1/fsp_bootmode.h rename to arch/x86/include/asm/fsp/fsp_bootmode.h diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index ed4335ed29..c2c5288ebd 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -7,12 +7,12 @@ #ifndef __FSP_SUPPORT_H__ #define __FSP_SUPPORT_H__ +#include #include #include #include #include #include "fsp_ffs.h" -#include "fsp_bootmode.h" #include #include From 0e23d7660a06978d8953cbeedd931ab0df01294f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:00:20 -0600 Subject: [PATCH 10/95] x86: Move fsp_ffs.h include to fsp_arch.h This include file is only used for FSP v1. Avoid including it from fdt_support.h so we can use the latter with FSP v2. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/fsp_arch.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/fsp_arch.h b/arch/x86/include/asm/fsp_arch.h index b223141c44..3b2077b392 100644 --- a/arch/x86/include/asm/fsp_arch.h +++ b/arch/x86/include/asm/fsp_arch.h @@ -15,6 +15,7 @@ */ #include +#include #include #include From 8fce3f29e4ad4d0cf2084ef63d46aa391ebbc1d7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:10 -0600 Subject: [PATCH 11/95] binman: Pass the toolpath to binman from the main Makefile Pass in the toolpath in case binman needs to use tools compiled in the U-Boot tools/ directory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 54da5cd51c..9ea602bdf0 100644 --- a/Makefile +++ b/Makefile @@ -1213,6 +1213,7 @@ u-boot.ldr: u-boot # Use 'make BINMAN_DEBUG=1' to enable debugging quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ + --toolpath $(objtree)/tools \ build -u -d u-boot.dtb -O . -m \ -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ $(BINMAN_$(@F)) From 1f338e00fa81e72380c788163fc3c63939bf5eea Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:11 -0600 Subject: [PATCH 12/95] binman: Allow selection of logging verbosity Support a new BINMAN_VERBOSE option to the build, to allow passing the -v flag to binman. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- Makefile | 3 ++- tools/binman/README | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9ea602bdf0..b68cbaf437 100644 --- a/Makefile +++ b/Makefile @@ -1214,7 +1214,8 @@ u-boot.ldr: u-boot quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ --toolpath $(objtree)/tools \ - build -u -d u-boot.dtb -O . -m \ + $(if $(BINMAN_VERBOSE),-v$(BINMAN_VERBOSE)) \ + build -u -d u-boot.dtb -O . -m \ -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ $(BINMAN_$(@F)) diff --git a/tools/binman/README b/tools/binman/README index b4f6392ab7..8e0f0a8c55 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -934,6 +934,12 @@ BINMAN_DEBUG=1 to your build: make sandbox_defconfig make BINMAN_DEBUG=1 +To enable verbose logging from binman, base BINMAN_VERBOSE to your build, which +adds a -v option to the call to binman: + + make sandbox_defconfig + make BINMAN_VERBOSE=5 + History / Credits ----------------- From 7e45bb0867fd88ff044a71903882e6ff098dea11 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:13 -0600 Subject: [PATCH 13/95] mtd: spi: Add 'struct spi_flash {' to the code At present spi_flash is defined to be spi_nor which is confusing since it is not possible to find the 'spi_flash' by normal text search. Add a comment to help with this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/linux/mtd/spi-nor.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 709b49d393..f9964a7664 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -246,7 +246,13 @@ enum spi_nor_option_flags { */ struct flash_info; -/* TODO: Remove, once all users of spi_flash interface are moved to MTD */ +/* + * TODO: Remove, once all users of spi_flash interface are moved to MTD + * + * struct spi_flash { + * Defined below (keep this text to enable searching for spi_flash decl) + * } + */ #define spi_flash spi_nor /** From 2e2c514a40e956d857707f157201c5606c0e9da0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:14 -0600 Subject: [PATCH 14/95] serial: ns16550: Allow serial to enabled/disabled in SPL At present this driver uses the wrong condition for including the code and drivers in SPL/TPL. Update it so that the code is only included if DM_SERIAL is enabled for SPL/TPL. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/serial/ns16550.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 6cf2be8f2b..01f334938e 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; #define UART_MCRVAL (UART_MCR_DTR | \ UART_MCR_RTS) /* RTS/DTR */ -#ifndef CONFIG_DM_SERIAL +#if !CONFIG_IS_ENABLED(DM_SERIAL) #ifdef CONFIG_SYS_NS16550_PORT_MAPPED #define serial_out(x, y) outb(x, (ulong)y) #define serial_in(y) inb((ulong)y) @@ -86,7 +86,7 @@ static inline int serial_in_shift(void *addr, int shift) #endif } -#ifdef CONFIG_DM_SERIAL +#if CONFIG_IS_ENABLED(DM_SERIAL) #ifndef CONFIG_SYS_NS16550_CLK #define CONFIG_SYS_NS16550_CLK 0 @@ -301,7 +301,7 @@ DEBUG_UART_FUNCS #endif -#ifdef CONFIG_DM_SERIAL +#if CONFIG_IS_ENABLED(DM_SERIAL) static int ns16550_serial_putc(struct udevice *dev, const char ch) { struct NS16550 *const com_port = dev_get_priv(dev); From 9bb746d819b32cdb6994ad5c09c59170e866ef3e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:16 -0600 Subject: [PATCH 15/95] spl: Avoid checking for Ctrl-C in SPL with print_buffer() We don't have a console in SPL so it doesn't make sense to check for Ctrl-C when printing a memory dump. Skip this so that print_buffer() can be used in SPL. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- lib/display_options.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/display_options.c b/lib/display_options.c index cff20f3755..ec16d75e0e 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -205,8 +205,10 @@ int print_buffer(ulong addr, const void *data, uint width, uint count, addr += thislinelen * width; count -= thislinelen; +#ifndef CONFIG_SPL_BUILD if (ctrlc()) return -1; +#endif } return 0; From a7da3d984db524cdec8336927a5825ffaa8443af Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:17 -0600 Subject: [PATCH 16/95] spl: handoff: Correct Kconfig condition for SPL and TPL At present these options can be enabled when bloblist is not enabled for SPL or TPL. This is incorrect as SPL handoff requires bloblist. Fix it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- common/spl/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index f467eca2be..62b93c112b 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -115,7 +115,7 @@ if SPL config SPL_HANDOFF bool "Pass hand-off information from SPL to U-Boot proper" - depends on HANDOFF + depends on HANDOFF && SPL_BLOBLIST default y help This option enables SPL to write handoff information. This can be @@ -1185,7 +1185,7 @@ if TPL config TPL_HANDOFF bool "Pass hand-off information from TPL to SPL and U-Boot proper" - depends on HANDOFF + depends on HANDOFF && TPL_BLOBLIST default y help This option enables TPL to write handoff information. This can be From 366291afe63fb4973161e01c29c43bc840a710a5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:18 -0600 Subject: [PATCH 17/95] spl: Add an arch-specific hook for writing to SPL handoff At present there is an arch-specific area in the SPL handoff area intended for use by arch-specific code, but there is no explicit call to fill in this data. Add a hook for this. Also use the hook to remove the sandbox-specific test code from write_spl_handoff(). Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/cpu/spl.c | 7 +++++++ common/spl/spl.c | 12 +++++++++--- include/handoff.h | 13 +++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 4f415c71d6..44c68a39bc 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -78,3 +78,10 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) } hang(); } + +int handoff_arch_save(struct spl_handoff *ho) +{ + ho->arch.magic = TEST_HANDOFF_MAGIC; + + return 0; +} diff --git a/common/spl/spl.c b/common/spl/spl.c index 082fa2bd94..730cd6b308 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -356,17 +356,23 @@ static int setup_spl_handoff(void) return 0; } +__weak int handoff_arch_save(struct spl_handoff *ho) +{ + return 0; +} + static int write_spl_handoff(void) { struct spl_handoff *ho; + int ret; ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff)); if (!ho) return -ENOENT; handoff_save_dram(ho); -#ifdef CONFIG_SANDBOX - ho->arch.magic = TEST_HANDOFF_MAGIC; -#endif + ret = handoff_arch_save(ho); + if (ret) + return ret; debug(SPL_TPL_PROMPT "Wrote SPL handoff\n"); return 0; diff --git a/include/handoff.h b/include/handoff.h index aacb0f5ebf..75d19b1f6e 100644 --- a/include/handoff.h +++ b/include/handoff.h @@ -31,6 +31,19 @@ struct spl_handoff { void handoff_save_dram(struct spl_handoff *ho); void handoff_load_dram_size(struct spl_handoff *ho); void handoff_load_dram_banks(struct spl_handoff *ho); + +/** + * handoff_arch_save() - Save arch-specific info into the handoff area + * + * This is defined to an empty function by default, but arch-specific code can + * define it to write to spi_handoff->arch. It is called from + * write_spl_handoff(). + * + * @ho: Handoff area to fill in + * @return 0 if OK, -ve on error + */ +int handoff_arch_save(struct spl_handoff *ho); + #endif #endif From 3cd71981531a767e5109368fede61931944bdb5c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:19 -0600 Subject: [PATCH 18/95] spl: Set up the bloblist in board_init_r() At present the bloblist is set up in spl_common_init() which can be called from spl_early_init(), i.e. before SDRAM is ready. This prevents the bloblist from being located in SDRAM, which is useful on some platforms where SRAM is inaccessible after U-Boot relocates (e.g. x86 CAR region). It doesn't serve much purpose to have the bloblist available early, since very little is known about the platform then, and the handoff info is written when SPL is about to jump to U-Boot. Move the code to board_init_r() to avoid any restrictions. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- common/spl/spl.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index 730cd6b308..5fdd6d0d03 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -410,23 +410,6 @@ static int spl_common_init(bool setup_malloc) return ret; } #endif - if (CONFIG_IS_ENABLED(BLOBLIST)) { - ret = bloblist_init(); - if (ret) { - debug("%s: Failed to set up bloblist: ret=%d\n", - __func__, ret); - return ret; - } - } - if (CONFIG_IS_ENABLED(HANDOFF)) { - int ret; - - ret = setup_spl_handoff(); - if (ret) { - puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n"); - hang(); - } - } if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { ret = fdtdec_setup(); if (ret) { @@ -604,6 +587,24 @@ void board_init_r(gd_t *dummy1, ulong dummy2) */ timer_init(); #endif + if (CONFIG_IS_ENABLED(BLOBLIST)) { + ret = bloblist_init(); + if (ret) { + debug("%s: Failed to set up bloblist: ret=%d\n", + __func__, ret); + puts(SPL_TPL_PROMPT "Cannot set up bloblist\n"); + hang(); + } + } + if (CONFIG_IS_ENABLED(HANDOFF)) { + int ret; + + ret = setup_spl_handoff(); + if (ret) { + puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n"); + hang(); + } + } #if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init(); From 8e83b76df41f2a7c36adae7af7aa40a0b1ab36a1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:20 -0600 Subject: [PATCH 19/95] spl: Add a function to determine the U-Boot phase U-Boot is built in three phases: TPL, SPL and U-Boot proper. Sometimes it is necessary to use different init code depending on the phase. For example, TPL might do very basic CPU init, SPL might do a little more and U-Boot proper might bring the CPU up to full speed and enable all cores. Add a function which allows easy determination of the current phase being built. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/spl.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/include/spl.h b/include/spl.h index e4640f3830..9be8d0ddcf 100644 --- a/include/spl.h +++ b/include/spl.h @@ -49,6 +49,66 @@ static inline bool u_boot_first_phase(void) return false; } +enum u_boot_phase { + PHASE_TPL, + PHASE_SPL, + PHASE_U_BOOT, +}; + +/** + * spl_phase() - Find out the phase of U-Boot + * + * This can be used to avoid #ifdef logic and use if() instead. + * + * For example, to include code only in TPL, you might do: + * + * #ifdef CONFIG_TPL_BUILD + * ... + * #endif + * + * but with this you can use: + * + * if (spl_phase() == PHASE_TPL) { + * ... + * } + * + * To include code only in SPL, you might do: + * + * #if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) + * ... + * #endif + * + * but with this you can use: + * + * if (spl_phase() == PHASE_SPL) { + * ... + * } + * + * To include code only in U-Boot proper, you might do: + * + * #ifndef CONFIG_SPL_BUILD + * ... + * #endif + * + * but with this you can use: + * + * if (spl_phase() == PHASE_U_BOOT) { + * ... + * } + * + * @return U-Boot phase + */ +static inline enum u_boot_phase spl_phase(void) +{ +#ifdef CONFIG_TPL_BUILD + return PHASE_TPL; +#elif CONFIG_SPL_BUILD + return PHASE_SPL; +#else + return PHASE_U_BOOT; +#endif +} + /* A string name for SPL or TPL */ #ifdef CONFIG_SPL_BUILD # ifdef CONFIG_TPL_BUILD From ff7abb85a43d501d29c43549eb3dceae25e00f10 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:24 -0600 Subject: [PATCH 20/95] x86: sysreset: Allow reset driver to be included in SPL/TPL At present this driver is always included in SPL and TPL, if U-Boot proper enables it. Update the Makefile to provide full control using the existing Kconfig options. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: make the Kconfig help text a little bit clearer] Signed-off-by: Bin Meng --- drivers/sysreset/Kconfig | 12 ++++++++++++ drivers/sysreset/Makefile | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index f565ae0310..5e6293ae69 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -107,6 +107,18 @@ config SYSRESET_X86 help Reboot support for generic x86 processor reset. +config SYSRESET_SPL_X86 + bool "Enable support for x86 processor reboot driver in SPL" + depends on X86 + help + Reboot support for generic x86 processor reset in SPL. + +config SYSRESET_TPL_X86 + bool "Enable support for x86 processor reboot driver in TPL" + depends on X86 + help + Reboot support for generic x86 processor reset in TPL. + config SYSRESET_MCP83XX bool "Enable support MPC83xx SoC family reboot driver" help diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index cf01492295..fff4a184a0 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -16,5 +16,5 @@ obj-$(CONFIG_SYSRESET_SOCFPGA_S10) += sysreset_socfpga_s10.o obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o -obj-$(CONFIG_SYSRESET_X86) += sysreset_x86.o +obj-$(CONFIG_$(SPL_TPL_)SYSRESET_X86) += sysreset_x86.o obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o From e2adc369ec5c10dda8b0e15cfc6399d81bcfc6d1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:25 -0600 Subject: [PATCH 21/95] x86: Rename some FSP functions to have an fsp_ prefix Given these exported function an fsp_ prefix since they are declared in an fsp.h header. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/cpu/baytrail/fsp_configs.c | 2 +- arch/x86/cpu/braswell/fsp_configs.c | 2 +- arch/x86/cpu/ivybridge/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/include/asm/fsp1/fsp_support.h | 6 +++--- arch/x86/lib/fsp1/fsp_car.S | 10 +++++----- arch/x86/lib/fsp1/fsp_support.c | 14 +++++++------- cmd/x86/fsp.c | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/x86/cpu/baytrail/fsp_configs.c b/arch/x86/cpu/baytrail/fsp_configs.c index 5b5d66aa5e..1d1948c91a 100644 --- a/arch/x86/cpu/baytrail/fsp_configs.c +++ b/arch/x86/cpu/baytrail/fsp_configs.c @@ -27,7 +27,7 @@ __weak void update_fsp_azalia_configs(struct azalia_config **azalia) * If the device tree does not specify an integer setting, use the default * provided in Intel's Baytrail_FSP_Gold4.tgz release FSP/BayleyBayFsp.bsf file. */ -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { struct upd_region *fsp_upd = &config->fsp_upd; diff --git a/arch/x86/cpu/braswell/fsp_configs.c b/arch/x86/cpu/braswell/fsp_configs.c index 607e333f21..60101d742d 100644 --- a/arch/x86/cpu/braswell/fsp_configs.c +++ b/arch/x86/cpu/braswell/fsp_configs.c @@ -40,7 +40,7 @@ __weak void update_fsp_gpio_configs(struct gpio_family **family, * If the device tree does not specify an integer setting, use the default * provided in Intel's Braswell release FSP/BraswellFsp.bsf file. */ -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { struct upd_region *fsp_upd = &config->fsp_upd; diff --git a/arch/x86/cpu/ivybridge/fsp_configs.c b/arch/x86/cpu/ivybridge/fsp_configs.c index 773c2b2a0a..0e6453c847 100644 --- a/arch/x86/cpu/ivybridge/fsp_configs.c +++ b/arch/x86/cpu/ivybridge/fsp_configs.c @@ -9,7 +9,7 @@ DECLARE_GLOBAL_DATA_PTR; -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { struct platform_config *plat_config = &config->plat_config; diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c index 0dd1901e07..381edd0761 100644 --- a/arch/x86/cpu/queensbay/fsp_configs.c +++ b/arch/x86/cpu/queensbay/fsp_configs.c @@ -7,7 +7,7 @@ #include #include -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { /* Initialize runtime buffer for fsp_init() */ diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index c2c5288ebd..a0095d0de4 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -25,7 +25,7 @@ * * This routine jumps to the C version of FSP continuation function */ -void asm_continuation(void); +void fsp_asm_continuation(void); /** * FSP initialization complete @@ -52,7 +52,7 @@ void fsp_continue(u32 status, void *hob_list); * * @retval: the offset of FSP header. If signature is invalid, returns 0. */ -struct fsp_header *find_fsp_header(void); +struct fsp_header *fsp_find_header(void); /** * FSP initialization wrapper function. @@ -172,7 +172,7 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len); * * @return: None */ -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf); /** diff --git a/arch/x86/lib/fsp1/fsp_car.S b/arch/x86/lib/fsp1/fsp_car.S index 8c54cea3db..a64a653435 100644 --- a/arch/x86/lib/fsp1/fsp_car.S +++ b/arch/x86/lib/fsp1/fsp_car.S @@ -20,10 +20,10 @@ car_init: car_init_start: post_code(POST_CAR_START) - lea find_fsp_header_romstack, %esp - jmp find_fsp_header + lea fsp_find_header_romstack, %esp + jmp fsp_find_header -find_fsp_header_ret: +fsp_find_header_ret: /* EAX points to FSP_INFO_HEADER */ mov %eax, %ebp @@ -91,8 +91,8 @@ die: * contain the function return address as well as the parameters. */ .balign 4 -find_fsp_header_romstack: - .long find_fsp_header_ret +fsp_find_header_romstack: + .long fsp_find_header_ret .balign 4 temp_ram_init_romstack: diff --git a/arch/x86/lib/fsp1/fsp_support.c b/arch/x86/lib/fsp1/fsp_support.c index 019a42f53f..b5b7d664a1 100644 --- a/arch/x86/lib/fsp1/fsp_support.c +++ b/arch/x86/lib/fsp1/fsp_support.c @@ -8,7 +8,7 @@ #include #include -struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void) +struct fsp_header *__attribute__((optimize("O0"))) fsp_find_header(void) { /* * This function may be called before the a stack is established, @@ -93,7 +93,7 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) struct upd_region *fsp_upd; #endif - fsp_hdr = find_fsp_header(); + fsp_hdr = fsp_find_header(); if (fsp_hdr == NULL) { /* No valid FSP info header was found */ panic("Invalid FSP header"); @@ -124,12 +124,12 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf)); /* Override any configuration if required */ - update_fsp_configs(&config_data, &rt_buf); + fsp_update_configs(&config_data, &rt_buf); memset(¶ms, 0, sizeof(struct fsp_init_params)); params.nvs_buf = nvs_buf; params.rt_buf = (struct fspinit_rtbuf *)&rt_buf; - params.continuation = (fsp_continuation_f)asm_continuation; + params.continuation = (fsp_continuation_f)fsp_asm_continuation; init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init); params_ptr = ¶ms; @@ -146,8 +146,8 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) asm volatile ( "pushl %0;" "call *%%eax;" - ".global asm_continuation;" - "asm_continuation:;" + ".global fsp_asm_continuation;" + "fsp_asm_continuation:;" "movl 4(%%esp), %%eax;" /* status */ "movl 8(%%esp), %%edx;" /* hob_list */ "jmp fsp_continue;" @@ -173,7 +173,7 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) u32 status; if (!fsp_hdr) - fsp_hdr = (struct fsp_header *)find_fsp_header(); + fsp_hdr = (struct fsp_header *)fsp_find_header(); if (fsp_hdr == NULL) { /* No valid FSP info header */ diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c index fb27624422..b3b663021b 100644 --- a/cmd/x86/fsp.c +++ b/cmd/x86/fsp.c @@ -11,7 +11,7 @@ DECLARE_GLOBAL_DATA_PTR; static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct fsp_header *hdr = find_fsp_header(); + struct fsp_header *hdr = fsp_find_header(); u32 img_addr = hdr->img_base; char *sign = (char *)&hdr->sign; int i; From 07f2f58b94b69ea962d1adea0b892825dea908e9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 24 Aug 2019 14:19:05 -0600 Subject: [PATCH 22/95] x86: fsp: Create a common fsp_support.h header Many support functions are common between FSP1 and FSP2. Add a new header to handle this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: remove forward declarations in fsp_support.h] Signed-off-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_support.h | 125 ++++++++++++++++++++++++ arch/x86/include/asm/fsp1/fsp_support.h | 119 +--------------------- drivers/pci/pci-uclass.c | 2 +- 3 files changed, 129 insertions(+), 117 deletions(-) create mode 100644 arch/x86/include/asm/fsp/fsp_support.h diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h new file mode 100644 index 0000000000..1c016faee8 --- /dev/null +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: Intel */ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + */ + +#ifndef __FSP_SUPPORT_H__ +#define __FSP_SUPPORT_H__ + +#include +#include +#include +#include +#include +#include +#include + +#define FSP_LOWMEM_BASE 0x100000UL +#define FSP_HIGHMEM_BASE 0x100000000ULL +#define UPD_TERMINATOR 0x55AA + +/** + * Find FSP header offset in FSP image + * + * @retval: the offset of FSP header. If signature is invalid, returns 0. + */ +struct fsp_header *fsp_find_header(void); + +/** + * FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase + * + * @retval: compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); + +/** + * This function retrieves the top of usable low memory. + * + * @hob_list: A HOB list pointer. + * + * @retval: Usable low memory top. + */ +u32 fsp_get_usable_lowmem_top(const void *hob_list); + +/** + * This function retrieves the top of usable high memory. + * + * @hob_list: A HOB list pointer. + * + * @retval: Usable high memory top. + */ +u64 fsp_get_usable_highmem_top(const void *hob_list); + +/** + * This function retrieves a special reserved memory region. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the GUID HOB data buffer length. + * If the GUID HOB is located, the length will be updated. + * @guid: A pointer to the owner guild. + * + * @retval: Reserved region start address. + * 0 if this region does not exist. + */ +u64 fsp_get_reserved_mem_from_guid(const void *hob_list, + u64 *len, const efi_guid_t *guid); + +/** + * This function retrieves the FSP reserved normal memory. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the FSP reserved memory length buffer. + * If the GUID HOB is located, the length will be updated. + * @retval: FSP reserved memory base + * 0 if this region does not exist. + */ +u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len); + +/** + * This function retrieves the TSEG reserved normal memory. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the TSEG reserved memory length buffer. + * If the GUID HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the TSEG reserved memory. + * @retval others: TSEG reserved memory base. + */ +u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); + +/** + * This function retrieves FSP Non-volatile Storage HOB buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the NVS data buffer length. + * If the HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the NVS HOB. + * @retval others: FSP NVS data buffer pointer. + */ +void *fsp_get_nvs_data(const void *hob_list, u32 *len); + +/** + * This function retrieves graphics information. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the graphics info HOB length. + * If the HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the graphics info HOB. + * @retval others: A pointer to struct hob_graphics_info. + */ +void *fsp_get_graphics_info(const void *hob_list, u32 *len); + +/** + * fsp_init_phase_pci() - Tell the FSP that we have completed PCI init + * + * @return 0 if OK, -EPERM if the FSP gave an error. + */ +int fsp_init_phase_pci(void); + +#endif diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index a0095d0de4..15c3a462e2 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -4,21 +4,11 @@ * Copyright (C) 2014, Bin Meng */ -#ifndef __FSP_SUPPORT_H__ -#define __FSP_SUPPORT_H__ +#ifndef __FSP1_SUPPORT_H__ +#define __FSP1_SUPPORT_H__ -#include -#include -#include -#include -#include +#include #include "fsp_ffs.h" -#include -#include - -#define FSP_LOWMEM_BASE 0x100000UL -#define FSP_HIGHMEM_BASE 0x100000000ULL -#define UPD_TERMINATOR 0x55AA /** * FSP Continuation assembly helper routine @@ -47,13 +37,6 @@ void fsp_init_done(void *hob_list); */ void fsp_continue(u32 status, void *hob_list); -/** - * Find FSP header offset in FSP image - * - * @retval: the offset of FSP header. If signature is invalid, returns 0. - */ -struct fsp_header *fsp_find_header(void); - /** * FSP initialization wrapper function. * @@ -63,83 +46,6 @@ struct fsp_header *fsp_find_header(void); */ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf); -/** - * FSP notification wrapper function - * - * @fsp_hdr: Pointer to FSP information header - * @phase: FSP initialization phase defined in enum fsp_phase - * - * @retval: compatible status code with EFI_STATUS defined in PI spec - */ -u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); - -/** - * This function retrieves the top of usable low memory. - * - * @hob_list: A HOB list pointer. - * - * @retval: Usable low memory top. - */ -u32 fsp_get_usable_lowmem_top(const void *hob_list); - -/** - * This function retrieves the top of usable high memory. - * - * @hob_list: A HOB list pointer. - * - * @retval: Usable high memory top. - */ -u64 fsp_get_usable_highmem_top(const void *hob_list); - -/** - * This function retrieves a special reserved memory region. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the GUID HOB data buffer length. - * If the GUID HOB is located, the length will be updated. - * @guid: A pointer to the owner guild. - * - * @retval: Reserved region start address. - * 0 if this region does not exist. - */ -u64 fsp_get_reserved_mem_from_guid(const void *hob_list, - u64 *len, const efi_guid_t *guid); - -/** - * This function retrieves the FSP reserved normal memory. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the FSP reserved memory length buffer. - * If the GUID HOB is located, the length will be updated. - * @retval: FSP reserved memory base - * 0 if this region does not exist. - */ -u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len); - -/** - * This function retrieves the TSEG reserved normal memory. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the TSEG reserved memory length buffer. - * If the GUID HOB is located, the length will be updated. - * - * @retval NULL: Failed to find the TSEG reserved memory. - * @retval others: TSEG reserved memory base. - */ -u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); - -/** - * This function retrieves FSP Non-volatile Storage HOB buffer and size. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the NVS data buffer length. - * If the HOB is located, the length will be updated. - * - * @retval NULL: Failed to find the NVS HOB. - * @retval others: FSP NVS data buffer pointer. - */ -void *fsp_get_nvs_data(const void *hob_list, u32 *len); - /** * This function retrieves Bootloader temporary stack buffer and size. * @@ -152,18 +58,6 @@ void *fsp_get_nvs_data(const void *hob_list, u32 *len); */ void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len); -/** - * This function retrieves graphics information. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the graphics info HOB length. - * If the HOB is located, the length will be updated. - * - * @retval NULL: Failed to find the graphics info HOB. - * @retval others: A pointer to struct hob_graphics_info. - */ -void *fsp_get_graphics_info(const void *hob_list, u32 *len); - /** * This function overrides the default configurations of FSP. * @@ -175,11 +69,4 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len); void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf); -/** - * fsp_init_phase_pci() - Tell the FSP that we have completed PCI init - * - * @return 0 if OK, -EPERM if the FSP gave an error. - */ -int fsp_init_phase_pci(void); - #endif diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index b73d0cd70a..ab3e1310eb 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -12,7 +12,7 @@ #include #include #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) -#include +#include #endif #include "pci_internal.h" From 86875f050bf433fa8078ae9c53d8493f79941f1a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:27 -0600 Subject: [PATCH 23/95] x86: fsp: Use if() instead of #ifdef Update a few #ifdefs to if() to improve build coverage. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: recover the codes that got wrongly deleted in dram_init()] Signed-off-by: Bin Meng --- arch/x86/lib/fsp1/fsp_common.c | 9 ++++----- arch/x86/lib/fsp1/fsp_dram.c | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index 591eef7b81..bfd76dccba 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -116,11 +116,10 @@ int arch_fsp_init(void) #endif if (!gd->arch.hob_list) { -#ifdef CONFIG_ENABLE_MRC_CACHE - nvs = fsp_prepare_mrc_cache(); -#else - nvs = NULL; -#endif + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) + nvs = fsp_prepare_mrc_cache(); + else + nvs = NULL; #ifdef CONFIG_HAVE_ACPI_RESUME if (prev_sleep_state == ACPI_S3) { diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 3bf65b495c..75341bc528 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -32,10 +32,9 @@ int dram_init(void) gd->ram_size = ram_size; post_code(POST_DRAM); -#ifdef CONFIG_ENABLE_MRC_CACHE - gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) + gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, &gd->arch.mrc_output_len); -#endif return 0; } From 12cf65a4d199e5d4ef8b167342579ab16d0f849b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Aug 2019 10:10:59 -0600 Subject: [PATCH 24/95] x86: fsp: Tidy up comment style a little The comments in the FSP code use a different style from the rest of the x86 code. I am not sure it this is intentional. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: fix 2 comment style issues] Signed-off-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_support.h | 42 ++++++++++++------------- arch/x86/include/asm/fsp1/fsp_support.h | 30 ++++++++++++------ arch/x86/include/asm/hob.h | 18 +++++------ arch/x86/lib/hob.c | 8 ++--- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 1c016faee8..a6b32bf95d 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -20,98 +20,98 @@ #define UPD_TERMINATOR 0x55AA /** - * Find FSP header offset in FSP image + * fsp_find_header() - Find FSP header offset in FSP image * - * @retval: the offset of FSP header. If signature is invalid, returns 0. + * @return the offset of FSP header. If signature is invalid, returns 0. */ struct fsp_header *fsp_find_header(void); /** - * FSP notification wrapper function + * fsp_notify() - FSP notification wrapper function * * @fsp_hdr: Pointer to FSP information header * @phase: FSP initialization phase defined in enum fsp_phase * - * @retval: compatible status code with EFI_STATUS defined in PI spec + * @return compatible status code with EFI_STATUS defined in PI spec */ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); /** - * This function retrieves the top of usable low memory. + * fsp_get_usable_lowmem_top() - retrieves the top of usable low memory * * @hob_list: A HOB list pointer. * - * @retval: Usable low memory top. + * @return Usable low memory top. */ u32 fsp_get_usable_lowmem_top(const void *hob_list); /** - * This function retrieves the top of usable high memory. + * fsp_get_usable_highmem_top() - retrieves the top of usable high memory * * @hob_list: A HOB list pointer. * - * @retval: Usable high memory top. + * @return Usable high memory top. */ u64 fsp_get_usable_highmem_top(const void *hob_list); /** - * This function retrieves a special reserved memory region. + * fsp_get_reserved_mem_from_guid() - retrieves a special reserved memory region * * @hob_list: A HOB list pointer. * @len: A pointer to the GUID HOB data buffer length. * If the GUID HOB is located, the length will be updated. * @guid: A pointer to the owner guild. * - * @retval: Reserved region start address. + * @return Reserved region start address. * 0 if this region does not exist. */ u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, const efi_guid_t *guid); /** - * This function retrieves the FSP reserved normal memory. + * fsp_get_fsp_reserved_mem() - retrieves the FSP reserved normal memory * * @hob_list: A HOB list pointer. * @len: A pointer to the FSP reserved memory length buffer. * If the GUID HOB is located, the length will be updated. - * @retval: FSP reserved memory base + * @return FSP reserved memory base * 0 if this region does not exist. */ u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len); /** - * This function retrieves the TSEG reserved normal memory. + * fsp_get_tseg_reserved_mem() - retrieves the TSEG reserved normal memory * * @hob_list: A HOB list pointer. * @len: A pointer to the TSEG reserved memory length buffer. * If the GUID HOB is located, the length will be updated. * - * @retval NULL: Failed to find the TSEG reserved memory. - * @retval others: TSEG reserved memory base. + * @return NULL: Failed to find the TSEG reserved memory. + * @return others: TSEG reserved memory base. */ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); /** - * This function retrieves FSP Non-volatile Storage HOB buffer and size. + * fsp_get_nvs_data() - retrieves FSP Non-volatile Storage HOB buffer and size * * @hob_list: A HOB list pointer. * @len: A pointer to the NVS data buffer length. * If the HOB is located, the length will be updated. * - * @retval NULL: Failed to find the NVS HOB. - * @retval others: FSP NVS data buffer pointer. + * @return NULL: Failed to find the NVS HOB. + * @return others: FSP NVS data buffer pointer. */ void *fsp_get_nvs_data(const void *hob_list, u32 *len); /** - * This function retrieves graphics information. + * fsp_get_graphics_info() - retrieves graphics information. * * @hob_list: A HOB list pointer. * @len: A pointer to the graphics info HOB length. * If the HOB is located, the length will be updated. * - * @retval NULL: Failed to find the graphics info HOB. - * @retval others: A pointer to struct hob_graphics_info. + * @return NULL: Failed to find the graphics info HOB. + * @return others: A pointer to struct hob_graphics_info. */ void *fsp_get_graphics_info(const void *hob_list, u32 *len); diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 15c3a462e2..236c167fc8 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -11,14 +11,14 @@ #include "fsp_ffs.h" /** - * FSP Continuation assembly helper routine + * fsp_asm_continuation() - FSP Continuation assembly helper routine * * This routine jumps to the C version of FSP continuation function */ void fsp_asm_continuation(void); /** - * FSP initialization complete + * fsp_init_done() - FSP initialization complete * * This is the function that indicates FSP initialization is complete and jumps * back to the bootloader with HOB list pointer as the parameter. @@ -28,17 +28,17 @@ void fsp_asm_continuation(void); void fsp_init_done(void *hob_list); /** - * FSP Continuation function + * fsp_continue() - FSP Continuation function * * @status: Always 0 * @hob_list: HOB list pointer * - * @retval: Never returns + * @return Never returns */ void fsp_continue(u32 status, void *hob_list); /** - * FSP initialization wrapper function. + * fsp_init() - FSP initialization wrapper function * * @stack_top: bootloader stack top address * @boot_mode: boot mode defined in fsp_bootmode.h @@ -47,24 +47,34 @@ void fsp_continue(u32 status, void *hob_list); void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf); /** - * This function retrieves Bootloader temporary stack buffer and size. + * fsp_notify() - FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase + * + * @return compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); + +/** + * fsp_get_bootloader_tmp_mem() - retrieves temporary stack buffer and size * * @hob_list: A HOB list pointer. * @len: A pointer to the bootloader temporary stack length. * If the HOB is located, the length will be updated. * - * @retval NULL: Failed to find the bootloader temporary stack HOB. - * @retval others: Bootloader temporary stackbuffer pointer. + * @return NULL: Failed to find the bootloader temporary stack HOB. + * @return others: Bootloader temporary stackbuffer pointer. */ void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len); /** - * This function overrides the default configurations of FSP. + * fsp_update_configs() - overrides the default configurations of FSP * * @config: A pointer to the FSP configuration data structure * @rt_buf: A pointer to the FSP runtime buffer data structure * - * @return: None + * @return None */ void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf); diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h index b4239821aa..56e11dbb28 100644 --- a/arch/x86/include/asm/hob.h +++ b/arch/x86/include/asm/hob.h @@ -135,7 +135,7 @@ struct hob_guid { * * @hdr: A pointer to a HOB. * - * @return: A pointer to the next HOB in the HOB list. + * @return A pointer to the next HOB in the HOB list. */ static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) @@ -152,8 +152,8 @@ static inline const struct hob_header *get_next_hob(const struct hob_header * * @hdr: A pointer to a HOB. * - * @retval true: The HOB specified by hdr is the last HOB in the HOB list. - * @retval false: The HOB specified by hdr is not the last HOB in the HOB list. + * @return true: The HOB specified by hdr is the last HOB in the HOB list. + * @return false: The HOB specified by hdr is not the last HOB in the HOB list. */ static inline bool end_of_hob(const struct hob_header *hdr) { @@ -169,7 +169,7 @@ static inline bool end_of_hob(const struct hob_header *hdr) * * @hdr: A pointer to a HOB. * - * @return: A pointer to the data buffer in a HOB. + * @return A pointer to the data buffer in a HOB. */ static inline void *get_guid_hob_data(const struct hob_header *hdr) { @@ -185,7 +185,7 @@ static inline void *get_guid_hob_data(const struct hob_header *hdr) * * @hdr: A pointer to a HOB. * - * @return: The size of the data buffer. + * @return The size of the data buffer. */ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) { @@ -198,7 +198,7 @@ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) * @type: HOB type to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching type; Otherwise NULL. + * @return A HOB object with matching type; Otherwise NULL. */ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list); @@ -208,7 +208,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list); * @guid: GUID to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching GUID; Otherwise NULL. + * @return A HOB object with matching GUID; Otherwise NULL. */ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list); @@ -221,8 +221,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, * If the GUID HOB is located, the length will be updated. * @guid A pointer to HOB GUID. * - * @retval NULL: Failed to find the GUID HOB. - * @retval others: GUID HOB data buffer pointer. + * @return NULL: Failed to find the GUID HOB. + * @return others: GUID HOB data buffer pointer. */ void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid); diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c index dcee29b04c..f2c47240ee 100644 --- a/arch/x86/lib/hob.c +++ b/arch/x86/lib/hob.c @@ -13,7 +13,7 @@ * @type: HOB type to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching type; Otherwise NULL. + * @return A HOB object with matching type; Otherwise NULL. */ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) { @@ -38,7 +38,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) * @guid: GUID to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching GUID; Otherwise NULL. + * @return A HOB object with matching GUID; Otherwise NULL. */ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list) @@ -65,8 +65,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, * If the GUID HOB is located, the length will be updated. * @guid A pointer to HOB GUID. * - * @retval NULL: Failed to find the GUID HOB. - * @retval others: GUID HOB data buffer pointer. + * @return NULL: Failed to find the GUID HOB. + * @return others: GUID HOB data buffer pointer. */ void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid) From e9de4a7cd31a08d7bd2afa842db5aca57b3a37cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 24 Aug 2019 14:10:32 -0600 Subject: [PATCH 25/95] x86: fsp: Move common dram functions into a common file Most of the DRAM functionality can be shared between FSP1 and FSP2. Move it into a shared file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: rebase the patch against u-boot-x86/next to get it applied cleanly] Signed-off-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_support.h | 9 +++ arch/x86/lib/Makefile | 1 + arch/x86/lib/fsp/Makefile | 5 ++ arch/x86/lib/fsp/fsp_dram.c | 90 ++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_dram.c | 83 ++---------------------- 5 files changed, 111 insertions(+), 77 deletions(-) create mode 100644 arch/x86/lib/fsp/Makefile create mode 100644 arch/x86/lib/fsp/fsp_dram.c diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index a6b32bf95d..215b0f7c9d 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -122,4 +122,13 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len); */ int fsp_init_phase_pci(void); +/** + * fsp_scan_for_ram_size() - Scan the HOB list to find the RAM size + * + * This sets gd->ram_size based on what it finds. + * + * @return 0 if OK, -ve on error + */ +int fsp_scan_for_ram_size(void); + #endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index a8c7448ee4..ca0ca1066b 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -43,6 +43,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZBOOT) += zimage.o endif obj-$(CONFIG_USE_HOB) += hob.o +obj-$(CONFIG_HAVE_FSP) += fsp/ obj-$(CONFIG_FSP_VERSION1) += fsp1/ obj-$(CONFIG_FSP_VERSION2) += fsp2/ diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile new file mode 100644 index 0000000000..e2160653de --- /dev/null +++ b/arch/x86/lib/fsp/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2019 Google LLC + +obj-y += fsp_dram.o diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c new file mode 100644 index 0000000000..8fe1e0bf73 --- /dev/null +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, Bin Meng + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int fsp_scan_for_ram_size(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; +}; + +int dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = 0; + gd->bd->bi_dram[0].size = gd->ram_size; + + return 0; +} + +unsigned int install_e820_map(unsigned int max_entries, + struct e820_entry *entries) +{ + unsigned int 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; + + num_entries++; + } + hdr = get_next_hob(hdr); + } + + /* Mark PCIe ECAM address range as reserved */ + entries[num_entries].addr = CONFIG_PCIE_ECAM_BASE; + entries[num_entries].size = CONFIG_PCIE_ECAM_SIZE; + entries[num_entries].type = E820_RESERVED; + num_entries++; + +#ifdef CONFIG_HAVE_ACPI_RESUME + /* + * Everything between U-Boot's stack and ram top needs to be + * reserved in order for ACPI S3 resume to work. + */ + entries[num_entries].addr = gd->start_addr_sp - CONFIG_STACK_SIZE; + entries[num_entries].size = gd->ram_top - gd->start_addr_sp + + CONFIG_STACK_SIZE; + entries[num_entries].type = E820_RESERVED; + num_entries++; +#endif + + return num_entries; +} diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 75341bc528..6a3349b42a 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -4,33 +4,16 @@ */ #include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; +#include int dram_init(void) { - phys_size_t ram_size = 0; - const struct hob_header *hdr; - struct hob_res_desc *res_desc; + int ret; - 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); + /* The FSP has already set up DRAM, so grab the info we need */ + ret = fsp_scan_for_ram_size(); + if (ret) + return ret; if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, @@ -39,14 +22,6 @@ int dram_init(void) return 0; } -int dram_init_banksize(void) -{ - gd->bd->bi_dram[0].start = 0; - gd->bd->bi_dram[0].size = gd->ram_size; - - return 0; -} - /* * 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. @@ -59,49 +34,3 @@ ulong board_get_usable_ram_top(ulong total_size) { return fsp_get_usable_lowmem_top(gd->arch.hob_list); } - -unsigned int install_e820_map(unsigned int max_entries, - struct e820_entry *entries) -{ - unsigned int 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; - - num_entries++; - } - hdr = get_next_hob(hdr); - } - - /* Mark PCIe ECAM address range as reserved */ - entries[num_entries].addr = CONFIG_PCIE_ECAM_BASE; - entries[num_entries].size = CONFIG_PCIE_ECAM_SIZE; - entries[num_entries].type = E820_RESERVED; - num_entries++; - -#ifdef CONFIG_HAVE_ACPI_RESUME - /* - * Everything between U-Boot's stack and ram top needs to be - * reserved in order for ACPI S3 resume to work. - */ - entries[num_entries].addr = gd->start_addr_sp - CONFIG_STACK_SIZE; - entries[num_entries].size = gd->ram_top - gd->start_addr_sp + \ - CONFIG_STACK_SIZE; - entries[num_entries].type = E820_RESERVED; - num_entries++; -#endif - - return num_entries; -} From b2d544a15d2edf8199e45e06c44b3e99ace906bc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:30 -0600 Subject: [PATCH 26/95] x86: Move common fsp functions into a common file Some of this file can be shared between FSP1 and FSP2. Move it into a shared file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_support.h | 17 ++++ arch/x86/include/asm/fsp1/fsp_support.h | 10 --- arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_common.c | 104 ++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_common.c | 87 -------------------- 5 files changed, 122 insertions(+), 97 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_common.c diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 215b0f7c9d..8dea2e71ea 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -131,4 +131,21 @@ int fsp_init_phase_pci(void); */ int fsp_scan_for_ram_size(void); +/** + * fsp_prepare_mrc_cache() - Find the DRAM training data from the MRC cache + * + * @return pointer to data, or NULL if no cache or no data found in the cache + */ +void *fsp_prepare_mrc_cache(void); + +/** + * fsp_notify() - FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase + * + * @return compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); + #endif diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 236c167fc8..a44a5504a4 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -46,16 +46,6 @@ void fsp_continue(u32 status, void *hob_list); */ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf); -/** - * fsp_notify() - FSP notification wrapper function - * - * @fsp_hdr: Pointer to FSP information header - * @phase: FSP initialization phase defined in enum fsp_phase - * - * @return compatible status code with EFI_STATUS defined in PI spec - */ -u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); - /** * fsp_get_bootloader_tmp_mem() - retrieves temporary stack buffer and size * diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile index e2160653de..e7a8427c2e 100644 --- a/arch/x86/lib/fsp/Makefile +++ b/arch/x86/lib/fsp/Makefile @@ -2,4 +2,5 @@ # # Copyright 2019 Google LLC +obj-y += fsp_common.o obj-y += fsp_dram.o diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c new file mode 100644 index 0000000000..6678d75ffd --- /dev/null +++ b/arch/x86/lib/fsp/fsp_common.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, Bin Meng + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int checkcpu(void) +{ + return 0; +} + +int print_cpuinfo(void) +{ + post_code(POST_CPU_INFO); + return default_print_cpuinfo(); +} + +int fsp_init_phase_pci(void) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); + status = fsp_notify(NULL, INIT_PHASE_PCI); + if (status) + debug("fail, error code %x\n", status); + else + debug("OK\n"); + + return status ? -EPERM : 0; +} + +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) + debug("fail, error code %x\n", status); + else + debug("OK\n"); +} + +void *fsp_prepare_mrc_cache(void) +{ + struct mrc_data_container *cache; + struct mrc_region entry; + int ret; + + ret = mrccache_get_region(NULL, &entry); + if (ret) + return NULL; + + cache = mrccache_find_current(&entry); + if (!cache) + return NULL; + + debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__, + cache->data, cache->data_size, cache->checksum); + + return cache->data; +} + +#ifdef CONFIG_HAVE_ACPI_RESUME +int fsp_save_s3_stack(void) +{ + struct udevice *dev; + int ret; + + if (gd->arch.prev_sleep_state == ACPI_S3) + return 0; + + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) { + debug("Cannot find RTC: err=%d\n", ret); + return -ENODEV; + } + + /* Save the stack address to CMOS */ + ret = rtc_write32(dev, CMOS_FSP_STACK_ADDR, gd->start_addr_sp); + if (ret) { + debug("Save stack address to CMOS: err=%d\n", ret); + return -EIO; + } + + return 0; +} +#endif diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index bfd76dccba..285ef72ebf 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -18,93 +18,6 @@ DECLARE_GLOBAL_DATA_PTR; -int checkcpu(void) -{ - return 0; -} - -int print_cpuinfo(void) -{ - post_code(POST_CPU_INFO); - return default_print_cpuinfo(); -} - -int fsp_init_phase_pci(void) -{ - u32 status; - - /* call into FspNotify */ - debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); - status = fsp_notify(NULL, INIT_PHASE_PCI); - if (status) - debug("fail, error code %x\n", status); - else - debug("OK\n"); - - return status ? -EPERM : 0; -} - -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) - debug("fail, error code %x\n", status); - else - debug("OK\n"); - - return; -} - -static __maybe_unused void *fsp_prepare_mrc_cache(void) -{ - struct mrc_data_container *cache; - struct mrc_region entry; - int ret; - - ret = mrccache_get_region(NULL, &entry); - if (ret) - return NULL; - - cache = mrccache_find_current(&entry); - if (!cache) - return NULL; - - debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__, - cache->data, cache->data_size, cache->checksum); - - return cache->data; -} - -#ifdef CONFIG_HAVE_ACPI_RESUME -int fsp_save_s3_stack(void) -{ - struct udevice *dev; - int ret; - - if (gd->arch.prev_sleep_state == ACPI_S3) - return 0; - - ret = uclass_get_device(UCLASS_RTC, 0, &dev); - if (ret) { - debug("Cannot find RTC: err=%d\n", ret); - return -ENODEV; - } - - /* Save the stack address to CMOS */ - ret = rtc_write32(dev, CMOS_FSP_STACK_ADDR, gd->start_addr_sp); - if (ret) { - debug("Save stack address to CMOS: err=%d\n", ret); - return -EIO; - } - - return 0; -} -#endif - int arch_fsp_init(void) { void *nvs; From 62888d840fb99d0375dc33ef7b3404377f451bcf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:31 -0600 Subject: [PATCH 27/95] x86: fsp: Move common support functions into a common file Some of this file can be shared between FSP1 and FSP2. Move it into a shared file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_support.c | 176 ++++++++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_support.c | 167 ------------------------------ 3 files changed, 177 insertions(+), 167 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_support.c diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile index e7a8427c2e..9e34856473 100644 --- a/arch/x86/lib/fsp/Makefile +++ b/arch/x86/lib/fsp/Makefile @@ -4,3 +4,4 @@ obj-y += fsp_common.o obj-y += fsp_dram.o +obj-y += fsp_support.o diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c new file mode 100644 index 0000000000..014de35e56 --- /dev/null +++ b/arch/x86/lib/fsp/fsp_support.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: Intel +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + */ + +#include +#include +#include + +u32 fsp_get_usable_lowmem_top(const void *hob_list) +{ + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + phys_addr_t phys_start; + u32 top; +#ifdef CONFIG_FSP_BROKEN_HOB + struct hob_mem_alloc *res_mem; + phys_addr_t mem_base = 0; +#endif + + /* Get the HOB list for processing */ + hdr = hob_list; + + /* * Collect memory ranges */ + top = FSP_LOWMEM_BASE; + 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) { + phys_start = res_desc->phys_start; + /* Need memory above 1MB to be collected here */ + if (phys_start >= FSP_LOWMEM_BASE && + phys_start < (phys_addr_t)FSP_HIGHMEM_BASE) + top += (u32)(res_desc->len); + } + } + +#ifdef CONFIG_FSP_BROKEN_HOB + /* + * Find out the lowest memory base address allocated by FSP + * for the boot service data + */ + if (hdr->type == HOB_TYPE_MEM_ALLOC) { + res_mem = (struct hob_mem_alloc *)hdr; + if (!mem_base) + mem_base = res_mem->mem_base; + if (res_mem->mem_base < mem_base) + mem_base = res_mem->mem_base; + } +#endif + + hdr = get_next_hob(hdr); + } + +#ifdef CONFIG_FSP_BROKEN_HOB + /* + * Check whether the memory top address is below the FSP HOB list. + * If not, use the lowest memory base address allocated by FSP as + * the memory top address. This is to prevent U-Boot relocation + * overwrites the important boot service data which is used by FSP, + * otherwise the subsequent call to fsp_notify() will fail. + */ + if (top > (u32)hob_list) { + debug("Adjust memory top address due to a buggy FSP\n"); + top = (u32)mem_base; + } +#endif + + return top; +} + +u64 fsp_get_usable_highmem_top(const void *hob_list) +{ + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + phys_addr_t phys_start; + u64 top; + + /* Get the HOB list for processing */ + hdr = hob_list; + + /* Collect memory ranges */ + top = FSP_HIGHMEM_BASE; + 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) { + phys_start = res_desc->phys_start; + /* Need memory above 4GB to be collected here */ + if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) + top += (u32)(res_desc->len); + } + } + hdr = get_next_hob(hdr); + } + + return top; +} + +u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, + const efi_guid_t *guid) +{ + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + + /* Get the HOB list for processing */ + hdr = hob_list; + + /* Collect memory ranges */ + while (!end_of_hob(hdr)) { + if (hdr->type == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_MEM_RESERVED) { + if (!guidcmp(&res_desc->owner, guid)) { + if (len) + *len = (u32)(res_desc->len); + + return (u64)(res_desc->phys_start); + } + } + } + hdr = get_next_hob(hdr); + } + + return 0; +} + +u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; + u64 length; + u32 base; + + base = (u32)fsp_get_reserved_mem_from_guid(hob_list, + &length, &guid); + if (len && base) + *len = (u32)length; + + return base; +} + +u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; + u64 length; + u32 base; + + base = (u32)fsp_get_reserved_mem_from_guid(hob_list, + &length, &guid); + if (len && base) + *len = (u32)length; + + return base; +} + +void *fsp_get_nvs_data(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} + +void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} + +void *fsp_get_graphics_info(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} diff --git a/arch/x86/lib/fsp1/fsp_support.c b/arch/x86/lib/fsp1/fsp_support.c index b5b7d664a1..c7a2c73846 100644 --- a/arch/x86/lib/fsp1/fsp_support.c +++ b/arch/x86/lib/fsp1/fsp_support.c @@ -197,170 +197,3 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) return status; } - -u32 fsp_get_usable_lowmem_top(const void *hob_list) -{ - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - phys_addr_t phys_start; - u32 top; -#ifdef CONFIG_FSP_BROKEN_HOB - struct hob_mem_alloc *res_mem; - phys_addr_t mem_base = 0; -#endif - - /* Get the HOB list for processing */ - hdr = hob_list; - - /* * Collect memory ranges */ - top = FSP_LOWMEM_BASE; - 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) { - phys_start = res_desc->phys_start; - /* Need memory above 1MB to be collected here */ - if (phys_start >= FSP_LOWMEM_BASE && - phys_start < (phys_addr_t)FSP_HIGHMEM_BASE) - top += (u32)(res_desc->len); - } - } - -#ifdef CONFIG_FSP_BROKEN_HOB - /* - * Find out the lowest memory base address allocated by FSP - * for the boot service data - */ - if (hdr->type == HOB_TYPE_MEM_ALLOC) { - res_mem = (struct hob_mem_alloc *)hdr; - if (!mem_base) - mem_base = res_mem->mem_base; - if (res_mem->mem_base < mem_base) - mem_base = res_mem->mem_base; - } -#endif - - hdr = get_next_hob(hdr); - } - -#ifdef CONFIG_FSP_BROKEN_HOB - /* - * Check whether the memory top address is below the FSP HOB list. - * If not, use the lowest memory base address allocated by FSP as - * the memory top address. This is to prevent U-Boot relocation - * overwrites the important boot service data which is used by FSP, - * otherwise the subsequent call to fsp_notify() will fail. - */ - if (top > (u32)hob_list) { - debug("Adjust memory top address due to a buggy FSP\n"); - top = (u32)mem_base; - } -#endif - - return top; -} - -u64 fsp_get_usable_highmem_top(const void *hob_list) -{ - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - phys_addr_t phys_start; - u64 top; - - /* Get the HOB list for processing */ - hdr = hob_list; - - /* Collect memory ranges */ - top = FSP_HIGHMEM_BASE; - 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) { - phys_start = res_desc->phys_start; - /* Need memory above 4GB to be collected here */ - if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) - top += (u32)(res_desc->len); - } - } - hdr = get_next_hob(hdr); - } - - return top; -} - -u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, - const efi_guid_t *guid) -{ - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - - /* Get the HOB list for processing */ - hdr = hob_list; - - /* Collect memory ranges */ - while (!end_of_hob(hdr)) { - if (hdr->type == HOB_TYPE_RES_DESC) { - res_desc = (struct hob_res_desc *)hdr; - if (res_desc->type == RES_MEM_RESERVED) { - if (!guidcmp(&res_desc->owner, guid)) { - if (len) - *len = (u32)(res_desc->len); - - return (u64)(res_desc->phys_start); - } - } - } - hdr = get_next_hob(hdr); - } - - return 0; -} - -u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; - u64 length; - u32 base; - - base = (u32)fsp_get_reserved_mem_from_guid(hob_list, - &length, &guid); - if ((len != 0) && (base != 0)) - *len = (u32)length; - - return base; -} - -u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; - u64 length; - u32 base; - - base = (u32)fsp_get_reserved_mem_from_guid(hob_list, - &length, &guid); - if ((len != 0) && (base != 0)) - *len = (u32)length; - - return base; -} - -void *fsp_get_nvs_data(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; - - return hob_get_guid_hob_data(hob_list, len, &guid); -} - -void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; - - return hob_get_guid_hob_data(hob_list, len, &guid); -} - -void *fsp_get_graphics_info(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID; - - return hob_get_guid_hob_data(hob_list, len, &guid); -} From fdeb6f7dc6ed81ba50f1b56eb4bade9108f5f145 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:32 -0600 Subject: [PATCH 28/95] efi: Move inline functions to unconditional part of header At present these two functions are defined in efi_loader.h but only if CONFIG_EFI_LOADER is enabled. But these are functions that are useful to other code, such as that which deals with Intel Handoff Blocks (HOBs). Move these to the top of the function. Possibly ascii2unicode() should not be an inline function, since this might impact code size. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/efi_loader.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 53b369945b..381da80cdc 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -12,6 +12,11 @@ #include #include +static inline int guidcmp(const void *g1, const void *g2) +{ + return memcmp(g1, g2, sizeof(efi_guid_t)); +} + /* No need for efi loader support in SPL */ #if CONFIG_IS_ENABLED(EFI_LOADER) @@ -563,11 +568,6 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype)) -static inline int guidcmp(const void *g1, const void *g2) -{ - return memcmp(g1, g2, sizeof(efi_guid_t)); -} - /* * Use these to indicate that your code / data should go into the EFI runtime * section and thus still be available when the OS is running From ceec18491c665bccb6702ac1ba835ca75e5e58a9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:33 -0600 Subject: [PATCH 29/95] x86: fsp: Add a few more definitions for FSP2 Add definitions for the FSP signature and the FSP init phase. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_infoheader.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/fsp/fsp_infoheader.h b/arch/x86/include/asm/fsp/fsp_infoheader.h index 86f78014b7..e72c052ed1 100644 --- a/arch/x86/include/asm/fsp/fsp_infoheader.h +++ b/arch/x86/include/asm/fsp/fsp_infoheader.h @@ -33,6 +33,19 @@ struct __packed fsp_header { #define FSP_HEADER_REVISION_1 1 #define FSP_HEADER_REVISION_2 2 -#define FSP_ATTR_GRAPHICS_SUPPORT (1 << 0) +enum fsp_type { + FSP_ATTR_COMP_TYPE_FSP_T = 1, + FSP_ATTR_COMP_TYPE_FSP_M = 2, + FSP_ATTR_COMP_TYPE_FSP_S = 3, +}; + +enum { + FSP_ATTR_GRAPHICS_SUPPORT = 1 << 0, + FSP_ATTR_COMP_TYPE_SHIFT = 28, + FSP_ATTR_COMP_TYPE_MASK = 0xfU << FSP_ATTR_COMP_TYPE_SHIFT, + +}; + +#define EFI_FSPH_SIGNATURE SIGNATURE_32('F', 'S', 'P', 'H') #endif From 46dd41fa5a8f08af903c7f0cfde9abfc16d7efe3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:34 -0600 Subject: [PATCH 30/95] x86: fsp: Add access to variable MRC data With FSP2 the non-volatile storage used by the FSP to init memory can be split into a fixed piece (determined at compile time) and a variable piece (determined at run time). Add support for reading the latter. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_hob.h | 4 ++++ arch/x86/include/asm/fsp/fsp_support.h | 12 ++++++++++++ arch/x86/lib/fsp/fsp_support.c | 7 +++++++ 3 files changed, 23 insertions(+) diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h index 3bb79c4b67..d248520e97 100644 --- a/arch/x86/include/asm/fsp/fsp_hob.h +++ b/arch/x86/include/asm/fsp/fsp_hob.h @@ -69,6 +69,10 @@ struct __packed hob_graphics_info { EFI_GUID(0x721acf02, 0x4d77, 0x4c2a, \ 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0) +#define FSP_VARIABLE_NV_DATA_HOB_GUID \ + EFI_GUID(0xa034147d, 0x690c, 0x4154, \ + 0x8d, 0xe6, 0xc0, 0x44, 0x64, 0x1d, 0xe9, 0x42) + #define FSP_BOOTLOADER_TEMP_MEM_HOB_GUID \ EFI_GUID(0xbbcff46c, 0xc8d3, 0x4113, \ 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e) diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 8dea2e71ea..4ac27d26f5 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -103,6 +103,18 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); */ void *fsp_get_nvs_data(const void *hob_list, u32 *len); +/** + * fsp_get_var_nvs_data() - get FSP variable Non-volatile Storage HOB buffer + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the NVS data buffer length. + * If the HOB is located, the length will be updated. + * + * @return NULL: Failed to find the NVS HOB. + * @return others: FSP NVS data buffer pointer. + */ +void *fsp_get_var_nvs_data(const void *hob_list, u32 *len); + /** * fsp_get_graphics_info() - retrieves graphics information. * diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 014de35e56..983888fd74 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -161,6 +161,13 @@ void *fsp_get_nvs_data(const void *hob_list, u32 *len) return hob_get_guid_hob_data(hob_list, len, &guid); } +void *fsp_get_var_nvs_data(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_VARIABLE_NV_DATA_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} + void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) { const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; From d3abc5d1ee5ffea5647a22ddfff82c01d507f962 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:35 -0600 Subject: [PATCH 31/95] x86: Move common Intel CPU info code into a function Add cpu_intel_get_info() to find out the CPU info on modern Intel CPUs. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: add parameter and return value descriptions] Signed-off-by: Bin Meng --- arch/x86/cpu/broadwell/cpu_full.c | 9 +-------- arch/x86/cpu/intel_common/cpu.c | 13 +++++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 8 ++------ arch/x86/include/asm/cpu_common.h | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index c1db184549..d8b8482658 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -645,14 +645,7 @@ void cpu_set_power_limits(int power_limit_1_time) static int broadwell_get_info(struct udevice *dev, struct cpu_info *info) { - msr_t msr; - - msr = msr_read(IA32_PERF_CTL); - info->cpu_freq = ((msr.lo >> 8) & 0xff) * BROADWELL_BCLK * 1000000; - info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | - 1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID; - - return 0; + return cpu_intel_get_info(info, BROADWELL_BCLK); } static int broadwell_get_count(struct udevice *dev) diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index d0ac17808c..9357626b5a 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -110,3 +111,15 @@ int cpu_set_flex_ratio_to_tdp_nominal(void) /* Not reached */ return -EINVAL; } + +int cpu_intel_get_info(struct cpu_info *info, int bclk) +{ + msr_t msr; + + msr = msr_read(IA32_PERF_CTL); + info->cpu_freq = ((msr.lo >> 8) & 0xff) * bclk * 1000000; + info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | + 1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID; + + return 0; +} diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 6edc3e233c..68e78e9478 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -436,12 +437,7 @@ static int model_206ax_init(struct udevice *dev) static int model_206ax_get_info(struct udevice *dev, struct cpu_info *info) { - msr_t msr; - - msr = msr_read(MSR_IA32_PERF_CTL); - info->cpu_freq = ((msr.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK * 1000000; - info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | - 1 << CPU_FEAT_UCODE; + return cpu_intel_get_info(info, SANDYBRIDGE_BCLK); return 0; } diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index 4c91a5dace..5e398bec94 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -8,6 +8,8 @@ #define IA32_PERF_CTL 0x199 +struct cpu_info; + /** * cpu_common_init() - Set up common CPU init * @@ -31,4 +33,18 @@ int cpu_common_init(void); */ int cpu_set_flex_ratio_to_tdp_nominal(void); +/** + * cpu_intel_get_info() - Obtain CPU info for Intel CPUs + * + * Most Intel CPUs use the same MSR to obtain the clock speed, and use the same + * features. This function fills in these values, given the value of the base + * clock in MHz (typically this should be set to 100). + * + * @info: cpu_info struct to fill in + * @bclk_mz: the base clock in MHz + * + * @return 0 always + */ +int cpu_intel_get_info(struct cpu_info *info, int bclk_mz); + #endif From 1eeb55755f4d50a9954d17cbb6f98b3285a9b976 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:36 -0600 Subject: [PATCH 32/95] x86: Add binman symbols to the image It is useful in SPL and TPL to access symbols from binman, such as the position and size of an entry in the ROM. Collect these symbols together in the SPL binaries. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/u-boot-spl.lds | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds index f20c0b810d..c1e9bfbf66 100644 --- a/arch/x86/cpu/u-boot-spl.lds +++ b/arch/x86/cpu/u-boot-spl.lds @@ -35,6 +35,12 @@ SECTIONS . = ALIGN(4); __data_end = .; __init_end = .; + . = ALIGN(4); + .binman_sym_table : { + __binman_sym_start = .; + KEEP(*(SORT(.binman_sym*))); + __binman_sym_end = .; + } _image_binary_end = .; From e46d00c77cd5a756e8cf3fae3b34eaa9ec012f0d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:37 -0600 Subject: [PATCH 33/95] x86: pci: Add a function to clear and set PCI config regs At present the x86 pre-DM equivalent of pci_bus_clrset_config32() does not exist. Add it to simplify PCI init code on x86. Also add the missing functions to this header. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/pci.c | 19 ++++++++++++++++++ arch/x86/include/asm/pci.h | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index c6218250e1..0ccde194d9 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -16,6 +16,10 @@ #include #include +/* + * TODO(sjg@chromium.org): Drop the first parameter from each of these + * functions since it is not used. + */ int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong *valuep, enum pci_size_t size) { @@ -54,6 +58,21 @@ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, return 0; } +int pci_x86_clrset_config(struct udevice *bus, pci_dev_t bdf, uint offset, + ulong clr, ulong set, enum pci_size_t size) +{ + ulong value; + int ret; + + ret = pci_x86_read_config(bus, bdf, offset, &value, size); + if (ret) + return ret; + value &= ~clr; + value |= set; + + return pci_x86_write_config(bus, bdf, offset, value, size); +} + void pci_assign_irqs(int bus, int device, u8 irq[4]) { pci_dev_t bdf; diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 118ac937d9..fb1edf3df7 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -17,12 +17,52 @@ #ifndef __ASSEMBLY__ +/** + * pci_x86_read_config() - Read a configuration value from a device + * + * This function can be called before PCI is set up in driver model. + * + * @bus: Bus to read from (ignored, can be NULL) + * @bdf: PCI device address: bus, device and function -see PCI_BDF() + * @offset: Register offset to read + * @valuep: Place to put the returned value + * @size: Access size + * @return 0 if OK, -ve on error + */ int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong *valuep, enum pci_size_t size); +/** + * pci_bus_write_config() - Write a configuration value to a device + * + * This function can be called before PCI is set up in driver model. + * + * @bus: Bus to read from (ignored, can be NULL) + * @bdf: PCI device address: bus, device and function -see PCI_BDF() + * @offset: Register offset to write + * @value: Value to write + * @size: Access size + * @return 0 if OK, -ve on error + */ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong value, enum pci_size_t size); +/** + * pci_bus_clrset_config32() - Update a configuration value for a device + * + * The register at @offset is updated to (oldvalue & ~clr) | set. This function + * can be called before PCI is set up in driver model. + * + * @bus: Bus to read from (ignored, can be NULL) + * @bdf: PCI device address: bus, device and function -see PCI_BDF() + * @offset: Register offset to update + * @clr: Bits to clear + * @set: Bits to set + * @return 0 if OK, -ve on error + */ +int pci_x86_clrset_config(struct udevice *bus, pci_dev_t bdf, uint offset, + ulong clr, ulong set, enum pci_size_t size); + /** * Assign IRQ number to a PCI device * From 14dd93beb71727edf0c7ee288f2ee1ceceb6317a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:38 -0600 Subject: [PATCH 34/95] x86: spl: Use hang() instead of a while() loop Use the standard hang() function when booting fails since this implements the defined U-Boot behaviour for this situation. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/spl.c | 3 +-- arch/x86/lib/tpl.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 5d5d1a9ca7..01a96d294b 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -183,8 +183,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) printf("Jumping to 64-bit U-Boot: Note many features are missing\n"); ret = cpu_jump_to_64bit_uboot(spl_image->entry_point); debug("ret=%d\n", ret); - while (1) - ; + hang(); } #endif diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c index 492a2d6521..3e662a8bda 100644 --- a/arch/x86/lib/tpl.c +++ b/arch/x86/lib/tpl.c @@ -108,8 +108,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { printf("Jumping to U-Boot SPL at %lx\n", (ulong)spl_image->entry_point); jump_to_spl(spl_image->entry_point); - while (1) - ; + hang(); } void spl_board_init(void) From daade119aa4b49d5ff6b1ebbdfeab0a8775c9344 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:39 -0600 Subject: [PATCH 35/95] x86: spl: Reduce priority of the basic SPL image loader This image loader works on systems where the flash is directly mapped to the last part of the 32-bit address space. On recent Intel systems (such as apollolake) this is not the case. Reduce the priority of this loader so that another one can override it. While we are here, rename the loader to BOOT_DEVICE_SPI_MMAP since BOOT_DEVICE_BOARD is not very descriptive. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/spl.h | 3 +-- arch/x86/lib/spl.c | 5 +++-- arch/x86/lib/tpl.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h index 27432b2897..1bef4877eb 100644 --- a/arch/x86/include/asm/spl.h +++ b/arch/x86/include/asm/spl.h @@ -10,8 +10,7 @@ #define CONFIG_SPL_BOARD_LOAD_IMAGE enum { - BOOT_DEVICE_SPI = 10, - BOOT_DEVICE_BOARD, + BOOT_DEVICE_SPI_MMAP = 10, BOOT_DEVICE_CROS_VBOOT, }; diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 01a96d294b..a739491303 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -11,6 +11,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -142,7 +143,7 @@ void board_init_f_r(void) u32 spl_boot_device(void) { - return BOOT_DEVICE_BOARD; + return BOOT_DEVICE_SPI_MMAP; } int spl_start_uboot(void) @@ -168,7 +169,7 @@ static int spl_board_load_image(struct spl_image_info *spl_image, return 0; } -SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image); +SPL_LOAD_IMAGE_METHOD("SPI", 5, BOOT_DEVICE_SPI_MMAP, spl_board_load_image); int spl_spi_load_image(void) { diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c index 3e662a8bda..cfefa78045 100644 --- a/arch/x86/lib/tpl.c +++ b/arch/x86/lib/tpl.c @@ -71,7 +71,7 @@ void board_init_f_r(void) u32 spl_boot_device(void) { return IS_ENABLED(CONFIG_CHROMEOS) ? BOOT_DEVICE_CROS_VBOOT : - BOOT_DEVICE_BOARD; + BOOT_DEVICE_SPI_MMAP; } int spl_start_uboot(void) @@ -97,7 +97,7 @@ static int spl_board_load_image(struct spl_image_info *spl_image, return 0; } -SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image); +SPL_LOAD_IMAGE_METHOD("SPI", 5, BOOT_DEVICE_SPI_MMAP, spl_board_load_image); int spl_spi_load_image(void) { From 12c81b2f4196ed7eb9f2d7d377b34280b1ca26c1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:40 -0600 Subject: [PATCH 36/95] x86: spl: Move broadwell-specific code out of generic x86 spl When TPL is running, broadwell needs to do different init from SPL. There is no need for this code to be in the generic x86 SPL file, so move it to arch_cpu_init(). Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/broadwell/cpu.c | 5 +++++ arch/x86/cpu/broadwell/cpu_full.c | 7 +++++++ arch/x86/lib/spl.c | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index bb7c361408..bba8cd1e94 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -67,7 +67,12 @@ int arch_cpu_init(void) { post_code(POST_CPU_INIT); +#ifdef CONFIG_TPL + /* Do a mini-init if TPL has already done the full init */ + return x86_cpu_reinit_f(); +#else return x86_cpu_init_f(); +#endif } int checkcpu(void) diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index d8b8482658..bd0b2037fa 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -81,6 +81,13 @@ static const u8 power_limit_time_msr_to_sec[] = { [0x11] = 128, }; +#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) +int arch_cpu_init(void) +{ + return 0; +} +#endif + /* * The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate * the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index a739491303..2baac91383 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -40,12 +40,7 @@ static int x86_spl_init(void) debug("%s: spl_init() failed\n", __func__); return ret; } -#ifdef CONFIG_TPL - /* Do a mini-init if TPL has already done the full init */ - ret = x86_cpu_reinit_f(); -#else ret = arch_cpu_init(); -#endif if (ret) { debug("%s: arch_cpu_init() failed\n", __func__); return ret; From c3863eadbc60d21b234ac5fb15c525b3cbc4f637 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:41 -0600 Subject: [PATCH 37/95] x86: fsp: Save usable RAM and hob_list in the handoff area The useable RAM is calculated when the RAM is inited. Save this value so that it can be easily used in U-Boot proper. Also save a pointer to the hob list so that it is accessible (before relocation only) in U-Boot proper. This avoids having to scan it in SPL, for everything U-Boot proper might need later. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: guard handoff_arch_save() with IS_ENABLED(CONFIG_USE_HOB)] Signed-off-by: Bin Meng --- arch/x86/cpu/intel_common/cpu_from_spl.c | 6 ++++++ arch/x86/include/asm/handoff.h | 8 ++++++++ arch/x86/lib/fsp/fsp_dram.c | 10 ++++++++++ 3 files changed, 24 insertions(+) diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c index a6233c75ce..b7bb524162 100644 --- a/arch/x86/cpu/intel_common/cpu_from_spl.c +++ b/arch/x86/cpu/intel_common/cpu_from_spl.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,11 @@ int arch_cpu_init(void) { int ret; +#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB) + struct spl_handoff *ho = gd->spl_handoff; + + gd->arch.hob_list = ho->arch.hob_list; +#endif ret = x86_cpu_reinit_f(); return ret; diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h index 4d18d59efe..aec49b9b81 100644 --- a/arch/x86/include/asm/handoff.h +++ b/arch/x86/include/asm/handoff.h @@ -9,7 +9,15 @@ #ifndef __x86_asm_handoff_h #define __x86_asm_handoff_h +/** + * struct arch_spl_handoff - architecture-specific handoff info + * + * @usable_ram_top: Value returned by board_get_usable_ram_top() in SPL + * @hob_list: Start of FSP hand-off blocks (HOBs) + */ struct arch_spl_handoff { + ulong usable_ram_top; + void *hob_list; }; #endif diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index 8fe1e0bf73..2d1023068f 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -88,3 +88,13 @@ unsigned int install_e820_map(unsigned int max_entries, return num_entries; } + +#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB) +int handoff_arch_save(struct spl_handoff *ho) +{ + ho->arch.usable_ram_top = fsp_get_usable_lowmem_top(gd->arch.hob_list); + ho->arch.hob_list = gd->arch.hob_list; + + return 0; +} +#endif From 6172e94c3c4729347624626d71e4eaf96ff9dcb9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:43 -0600 Subject: [PATCH 38/95] x86: Change condition for using CAR At present we assume that CAR (Cache-as-RAM) is used if HOBs (Hand-off blocks) are not, since HOBs typically indicate that an FSP is in use, and FSPs handle the CAR init. However this is a bit indirect, and for FSP2 machines which use their own CAR implementation (such as apollolake) but use the FSP for other functions, the logic is wrong. To fix this, add a dedicated Kconfig option to indicate when CAR is used. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: fix a typo in the commit message] Signed-off-by: Bin Meng --- arch/x86/Kconfig | 8 ++++++++ arch/x86/cpu/start.S | 4 ++-- configs/slimbootloader_defconfig | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 314f8def7a..47bf28c434 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -364,6 +364,14 @@ config HAVE_FSP Note: Without this binary U-Boot will not be able to set up its SDRAM so will not boot. +config USE_CAR + bool "Use Cache-As-RAM (CAR) to get temporary RAM at start-up" + default y if !HAVE_FSP + help + Select this option if your board uses CAR init code, typically in a + car.S file, to get some initial memory for code execution. This is + common with Intel CPUs which don't use FSP. + choice prompt "FSP version" depends on HAVE_FSP diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 3c9bdf2a9d..9b76394274 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -90,7 +90,7 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: -#ifndef CONFIG_USE_HOB +#ifdef CONFIG_USE_CAR /* * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) @@ -130,7 +130,7 @@ car_init_ret: /* Get address of global_data */ mov %fs:0, %edx -#ifdef CONFIG_USE_HOB +#if defined(CONFIG_USE_HOB) && !defined(CONFIG_USE_CAR) /* Store the HOB list if we have one */ test %esi, %esi jz skip_hob diff --git a/configs/slimbootloader_defconfig b/configs/slimbootloader_defconfig index f9fecff45e..3cbb83c7a4 100644 --- a/configs/slimbootloader_defconfig +++ b/configs/slimbootloader_defconfig @@ -18,3 +18,4 @@ CONFIG_REGMAP=y CONFIG_SYSCON=y # CONFIG_PCI_PNP is not set CONFIG_CONSOLE_SCROLL_LINES=5 +# CONFIG_USE_CAR is not set From 08deb6d36f0a830181a3acce5eaece9431a828c0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:44 -0600 Subject: [PATCH 39/95] x86: Add more comments to the start-up code The full start-up sequence (TPL->SPL->U-Boot) can be a bit confusing since each phase has its own 'start' file. Add comments to explain this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/start.S | 12 ++++++++++++ arch/x86/cpu/start_from_spl.S | 5 +++-- arch/x86/cpu/start_from_tpl.S | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 9b76394274..01524635e9 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -2,6 +2,18 @@ /* * U-Boot - x86 Startup Code * + * This is always the first code to run from the U-Boot source. To spell it out: + * + * 1. When TPL (Tertiary Program Loader) is enabled, the boot flow is + * TPL->SPL->U-Boot and this file is used for TPL. Then start_from_tpl.S is used + * for SPL and start_from_spl.S is used for U-Boot proper. + * + * 2. When SPL (Secondary Program Loader) is enabled, but not TPL, the boot + * flow is SPL->U-Boot and this file is used for SPL. Then start_from_spl.S is + * used for U-Boot proper. + * + * 3. When neither TPL nor SPL is used, this file is used for U-Boot proper. + * * (C) Copyright 2008-2011 * Graeme Russ, * diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S index 4d4e5d0758..a73b4d7c45 100644 --- a/arch/x86/cpu/start_from_spl.S +++ b/arch/x86/cpu/start_from_spl.S @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * 32-bit x86 Startup Code when running from SPL - * + * 32-bit x86 Startup Code when running from SPL. This is the startup code in + * U-Boot proper, when SPL is used. + * Copyright 2018 Google, Inc * Written by Simon Glass */ diff --git a/arch/x86/cpu/start_from_tpl.S b/arch/x86/cpu/start_from_tpl.S index 44b5363a68..9a4974a5f1 100644 --- a/arch/x86/cpu/start_from_tpl.S +++ b/arch/x86/cpu/start_from_tpl.S @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * 32-bit x86 Startup Code when running from TPL + * 32-bit x86 Startup Code when running from TPL. This is the startup code in + * SPL, when TPL is used. * * Copyright 2018 Google, Inc * Written by Simon Glass From ebe002cd180c4b9f7f92720acaf13e712a1cce93 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:46 -0600 Subject: [PATCH 40/95] x86: Add various MTRR indexes and values Add some new MTRRs used by Apollolake as well as a mask for the MTRR type. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/msr-index.h | 22 ++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 1 + 2 files changed, 23 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 9c1dbe61d5..1a02d8c8fe 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -43,6 +43,12 @@ #define MSR_PIC_MSG_CONTROL 0x2e #define PLATFORM_INFO_SET_TDP (1 << 29) +#define MSR_MTRR_CAP_MSR 0x0fe +#define MSR_MTRR_CAP_SMRR (1 << 11) +#define MSR_MTRR_CAP_WC (1 << 10) +#define MSR_MTRR_CAP_FIX (1 << 8) +#define MSR_MTRR_CAP_VCNT 0xff + #define MSR_IA32_PERFCTR0 0x000000c1 #define MSR_IA32_PERFCTR1 0x000000c2 #define MSR_FSB_FREQ 0x000000cd @@ -67,6 +73,11 @@ #define ENABLE_ULFM_AUTOCM_MASK (1 << 2) #define ENABLE_INDP_AUTOCM_MASK (1 << 3) +#define MSR_EMULATE_PM_TIMER 0x121 +#define EMULATE_DELAY_OFFSET_VALUE 20 +#define EMULATE_PM_TMR_EN (1 << 16) +#define EMULATE_DELAY_VALUE 0x13 + #define MSR_IA32_SYSENTER_CS 0x00000174 #define MSR_IA32_SYSENTER_ESP 0x00000175 #define MSR_IA32_SYSENTER_EIP 0x00000176 @@ -78,9 +89,14 @@ #define MSR_FLEX_RATIO 0x194 #define FLEX_RATIO_LOCK (1 << 20) #define FLEX_RATIO_EN (1 << 16) +/* This is burst mode BIT 38 in IA32_MISC_ENABLE MSR at offset 1A0h */ +#define BURST_MODE_DISABLE (1 << 6) #define MSR_IA32_MISC_ENABLES 0x000001a0 #define MSR_TEMPERATURE_TARGET 0x1a2 +#define MSR_PREFETCH_CTL 0x1a4 +#define PREFETCH_L1_DISABLE (1 << 0) +#define PREFETCH_L2_DISABLE (1 << 2) #define MSR_OFFCORE_RSP_0 0x000001a6 #define MSR_OFFCORE_RSP_1 0x000001a7 #define MSR_MISC_PWR_MGMT 0x1aa @@ -600,6 +616,12 @@ #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 #define MSR_IA32_VMX_VMFUNC 0x00000491 +#define MSR_IA32_PQR_ASSOC 0xc8f +/* MSR bits 33:32 encode slot number 0-3 */ +#define MSR_IA32_PQR_ASSOC_MASK (1 << 0 | 1 << 1) + +#define MSR_L2_QOS_MASK(reg) (0xd10 + (reg)) + /* VMX_BASIC bits and bitmasks */ #define VMX_BASIC_VMCS_SIZE_SHIFT 32 #define VMX_BASIC_64 0x0001000000000000LLU diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 2d897f82ef..6f29e75ce6 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -25,6 +25,7 @@ #define MTRR_CAP_FIX (1 << 8) #define MTRR_CAP_VCNT_MASK 0xff +#define MTRR_DEF_TYPE_MASK 0xff #define MTRR_DEF_TYPE_EN (1 << 11) #define MTRR_DEF_TYPE_FIX_EN (1 << 10) From bdeb2bccbf40474eca8ef039ab794ba46cd971e5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:11:47 -0600 Subject: [PATCH 41/95] x86: Rename turbo ratio MSR to MSR_TURBO_RATIO_LIMIT This MSR number is used on most modern Intel processors, so drop the confusing NHM prefix (which might mean Nehalem). Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: drop MSR_IVT_TURBO_RATIO_LIMIT as no code uses it] Signed-off-by: Bin Meng --- arch/x86/cpu/broadwell/cpu_full.c | 2 +- arch/x86/include/asm/msr-index.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index bd0b2037fa..9686cf5e0e 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -346,7 +346,7 @@ static void set_max_ratio(void) /* Check for configurable TDP option */ if (turbo_get_state() == TURBO_ENABLED) { - msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT); + msr = msr_read(MSR_TURBO_RATIO_LIMIT); perf_ctl.lo = (msr.lo & 0xff) << 8; } else if (cpu_config_tdp_levels()) { /* Set to nominal TDP ratio */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1a02d8c8fe..6cb5870809 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -101,8 +101,7 @@ #define MSR_OFFCORE_RSP_1 0x000001a7 #define MSR_MISC_PWR_MGMT 0x1aa #define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) -#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad -#define MSR_IVT_TURBO_RATIO_LIMIT 0x000001ae +#define MSR_TURBO_RATIO_LIMIT 0x000001ad #define MSR_IA32_ENERGY_PERFORMANCE_BIAS 0x1b0 #define ENERGY_POLICY_PERFORMANCE 0 From d3e773613b6d159204de4894a4e0d191717ce318 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:45 -0600 Subject: [PATCH 42/95] dm: core: Use U-Boot logging instead of pr_debug() The pr_debug() functions do not response to setting the log level and in fact have their own separate log level. Use U-Boot logging instead. Perhaps we should make these options redirect to log_debug(), etc.? Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/core/lists.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/core/lists.c b/drivers/core/lists.c index a1f828463e..4681b3e5dd 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -6,6 +6,8 @@ * Marek Vasut */ +#define LOG_CATEGORY LOGC_DM + #include #include #include @@ -139,13 +141,13 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, if (devp) *devp = NULL; name = ofnode_get_name(node); - pr_debug("bind node %s\n", name); + log_debug("bind node %s\n", name); compat_list = ofnode_get_property(node, "compatible", &compat_length); if (!compat_list) { if (compat_length == -FDT_ERR_NOTFOUND) { - pr_debug("Device '%s' has no compatible string\n", - name); + log_debug("Device '%s' has no compatible string\n", + name); return 0; } @@ -160,8 +162,8 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, */ for (i = 0; i < compat_length; i += strlen(compat) + 1) { compat = compat_list + i; - pr_debug(" - attempt to match compatible string '%s'\n", - compat); + log_debug(" - attempt to match compatible string '%s'\n", + compat); for (entry = driver; entry != driver + n_ents; entry++) { ret = driver_check_compatible(entry->of_match, &id, @@ -178,11 +180,13 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, return 0; } - pr_debug(" - found match at '%s'\n", entry->name); + log_debug(" - found match at '%s': '%s' matches '%s'\n", + entry->name, entry->of_match->compatible, + id->compatible); ret = device_bind_with_driver_data(parent, entry, name, id->data, node, &dev); if (ret == -ENODEV) { - pr_debug("Driver '%s' refuses to bind\n", entry->name); + log_debug("Driver '%s' refuses to bind\n", entry->name); continue; } if (ret) { @@ -198,7 +202,7 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, } if (!found && !result && ret != -ENODEV) - pr_debug("No match for node '%s'\n", name); + log_debug("No match for node '%s'\n", name); return result; } From c8b31cce45477dea51b3c65b2c0e12ea9cced9f0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:47 -0600 Subject: [PATCH 43/95] dm: core: Drop a few early returns Two functions in this file return early for no good reason. Adjust the code to match the standard DM style of returning 0 at the end of the function on success. Oddly enough this save 12 bytes of code size on ARM. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/core/uclass.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index b33296542f..af575bbeb7 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -714,8 +714,11 @@ int uclass_pre_probe_device(struct udevice *dev) if (!dev->parent) return 0; uc_drv = dev->parent->uclass->uc_drv; - if (uc_drv->child_pre_probe) - return uc_drv->child_pre_probe(dev); + if (uc_drv->child_pre_probe) { + ret = uc_drv->child_pre_probe(dev); + if (ret) + return ret; + } return 0; } @@ -735,8 +738,11 @@ int uclass_post_probe_device(struct udevice *dev) } uc_drv = dev->uclass->uc_drv; - if (uc_drv->post_probe) - return uc_drv->post_probe(dev); + if (uc_drv->post_probe) { + ret = uc_drv->post_probe(dev); + if (ret) + return ret; + } return 0; } From fdd72be486144f154fdfac91e7bfc2d503fea9fb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:48 -0600 Subject: [PATCH 44/95] dm: core: Add documentation on how to debug driver model Sometimes devices don't appear and it can be confusing. Add a few notes to help with this situation. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: fix 2 issues in the doc and include the doc in the index.rst] Signed-off-by: Bin Meng --- doc/driver-model/debugging.rst | 62 ++++++++++++++++++++++++++++++++++ doc/driver-model/index.rst | 1 + 2 files changed, 63 insertions(+) create mode 100644 doc/driver-model/debugging.rst diff --git a/doc/driver-model/debugging.rst b/doc/driver-model/debugging.rst new file mode 100644 index 0000000000..4f4a8d4805 --- /dev/null +++ b/doc/driver-model/debugging.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Simon Glass + +Debugging driver model +====================== + +This document aims to provide help when you cannot work out why driver model is +not doing what you expect. + + +Useful techniques in general +---------------------------- + +Here are some useful debugging features generally. + + - If you are writing a new feature, consider doing it in sandbox instead of + on your board. Sandbox has no limits, allows easy debugging (e.g. gdb) and + you can write emulators for most common devices. + - Put '#define DEBUG' at the top of a file, to activate all the debug() and + log_debug() statements in that file. + - Where logging is used, change the logging level, e.g. in SPL with + CONFIG_SPL_LOG_MAX_LEVEL=7 (which is LOGL_DEBUG) and + CONFIG_LOG_DEFAULT_LEVEL=7 + - Where logging of return values is implemented with log_msg_ret(), set + CONFIG_LOG_ERROR_RETURN=y to see exactly where the error is happening + - Make sure you have a debug UART enabled - see CONFIG_DEBUG_UART. With this + you can get serial output (printf(), etc.) before the serial driver is + running. + - Use a JTAG emulator to set breakpoints and single-step through code + +Not that most of these increase code/data size somewhat when enabled. + + +Failure to locate a device +-------------------------- + +Let's say you have uclass_first_device_err() and it is not finding anything. + +If it is returning an error, then that gives you a clue. Look up linux/errno.h +to see errors. Common ones are: + + - -ENOMEM which indicates that memory is short. If it happens in SPL or + before relocation in U-Boot, check CONFIG_SPL_SYS_MALLOC_F_LEN and + CONFIG_SYS_MALLOC_F_LEN as they may need to be larger. Add '#define DEBUG' + at the very top of malloc_simple.c to get an idea of where your memory is + going. + - -EINVAL which typically indicates that something was missing or wrong in + the device tree node. Check that everything is correct and look at the + ofdata_to_platdata() method in the driver. + +If there is no error, you should check if the device is actually bound. Call +dm_dump_all() just before you locate the device to make sure it exists. + +If it does not exist, check your device tree compatible strings match up with +what the driver expects (in the struct udevice_id array). + +If you are using of-platdata (e.g. CONFIG_SPL_OF_PLATDATA), check that the +driver name is the same as the first compatible string in the device tree (with +invalid-variable characters converted to underscore). + +If you are really stuck, #define DEBUG at the top of lists.c should show you +what is going on. diff --git a/doc/driver-model/index.rst b/doc/driver-model/index.rst index ea32c36335..6d55774b4c 100644 --- a/doc/driver-model/index.rst +++ b/doc/driver-model/index.rst @@ -6,6 +6,7 @@ Driver Model .. toctree:: :maxdepth: 2 + debugging design fdt-fixup fs_firmware_loader From fe9a967925521c78fb52621ee760ead381a80cb7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:51 -0600 Subject: [PATCH 45/95] dm: test: Fix running of multiple test from command line At present when multiple 'ut dm' commands are executed, all but the first is run with a flat tree, even if live tree is enabled. This is because the live tree node pointer is set to NULL and never restored. This does not affect normal test running, which just runs all the test in one go, but can be confusing when several individual tests are run during the same U-Boot run. Correct this by restoring the pointer. Fixes: c166c47ba3 (dm: test: Add support for running tests with livetree) Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- test/dm/test-main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/dm/test-main.c b/test/dm/test-main.c index 5d79ce641d..487d8b9627 100644 --- a/test/dm/test-main.c +++ b/test/dm/test-main.c @@ -188,8 +188,12 @@ static int dm_test_main(const char *test_name) else printf("Failures: %d\n", uts->fail_count); + /* Put everything back to normal so that sandbox works as expected */ +#ifdef CONFIG_OF_LIVE + gd->of_root = uts->of_root; +#endif gd->dm_root = NULL; - ut_assertok(dm_init(false)); + ut_assertok(dm_init(IS_ENABLED(CONFIG_OF_LIVE))); dm_scan_platdata(false); dm_scan_fdt(gd->fdt_blob, false); From ad9504793622c3c745460572b236109e2d69bae4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:52 -0600 Subject: [PATCH 46/95] dm: test: Don't fail when tests are skipped due to build At present tests that are marked as only for livetree fail when executed on sandbox_flattree. They cannot actually be executed, but we should not resport them as 'not found', since this causes errors. Instead, they should be silently skipped. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- test/dm/test-main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/dm/test-main.c b/test/dm/test-main.c index 487d8b9627..74f77ccc84 100644 --- a/test/dm/test-main.c +++ b/test/dm/test-main.c @@ -130,7 +130,7 @@ static int dm_test_main(const char *test_name) const int n_ents = ll_entry_count(struct unit_test, dm_test); struct unit_test_state *uts = &global_dm_test_state; struct unit_test *test; - int run_count; + int found; uts->priv = &_global_priv_dm_test_state; uts->fail_count = 0; @@ -148,7 +148,7 @@ static int dm_test_main(const char *test_name) if (!test_name) printf("Running %d driver model tests\n", n_ents); - run_count = 0; + found = 0; #ifdef CONFIG_OF_LIVE uts->of_root = gd->of_root; #endif @@ -180,10 +180,10 @@ static int dm_test_main(const char *test_name) ut_assertok(dm_do_test(uts, test, false)); runs++; } - run_count += runs; + found++; } - if (test_name && !run_count) + if (test_name && !found) printf("Test '%s' not found\n", test_name); else printf("Failures: %d\n", uts->fail_count); From ea14778d0680f8a3f262a06ceb52ea17deb6a104 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:53 -0600 Subject: [PATCH 47/95] dm: core: Call ofdata_to_platdata() with of-platdata At present this function is never called when of-platdata is enabled since we never have a device tree. However, this function is responsible for copying over the of-platdata, so we must call it. Otherwise the probe() method would have to be used. Correct this and fix the sandbox serial driver to not read from the device tree and try to write to what is read-only platdata on some platforms. Fixes: 396e343b3d (dm: core: Allow binding a device from a live tree) Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/core/device.c | 3 ++- drivers/serial/sandbox.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/core/device.c b/drivers/core/device.c index 05dadf98f9..84f0f0fbf0 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -404,7 +404,8 @@ int device_probe(struct udevice *dev) goto fail; } - if (drv->ofdata_to_platdata && dev_has_of_node(dev)) { + if (drv->ofdata_to_platdata && + (CONFIG_IS_ENABLED(OF_PLATDATA) || dev_has_of_node(dev))) { ret = drv->ofdata_to_platdata(dev); if (ret) goto fail; diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index 33102fc872..2f7bc24887 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -220,6 +220,8 @@ static int sandbox_serial_ofdata_to_platdata(struct udevice *dev) const char *colour; int i; + if (CONFIG_IS_ENABLED(OF_PLATDATA)) + return 0; plat->colour = -1; colour = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "sandbox,text-colour", NULL); From 4805a7af8ebd4c604e1e32355927ec5035685121 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:55 -0600 Subject: [PATCH 48/95] dm: core: Correct the return value for uclass_find_first_device() This function returns -ENODEV when there is no device. This is inconsistent with other functions, such as uclass_find_next_device(), which returns 0. Update it and tidy up the incorrect '-1' values in the comments. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- drivers/core/uclass.c | 2 +- include/dm/uclass-internal.h | 4 ++-- test/dm/core.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index af575bbeb7..f217876cd2 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -225,7 +225,7 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp) if (ret) return ret; if (list_empty(&uc->dev_head)) - return -ENODEV; + return 0; *devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node); diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h index 6977995246..6e3f15c2b0 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -69,7 +69,7 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp); * The device is not prepared for use - this is an internal function. * The function uclass_get_device_tail() can be used to probe the device. * - * @return 0 if OK (found or not found), -1 on error + * @return 0 if OK (found or not found), -ve on error */ int uclass_find_first_device(enum uclass_id id, struct udevice **devp); @@ -81,7 +81,7 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp); * The device is not prepared for use - this is an internal function. * The function uclass_get_device_tail() can be used to probe the device. * - * @return 0 if OK (found or not found), -1 on error + * @return 0 if OK (found or not found), -ve on error */ int uclass_find_next_device(struct udevice **devp); diff --git a/test/dm/core.c b/test/dm/core.c index edd55b05d6..f74c430843 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -749,8 +749,7 @@ static int dm_test_uclass_devices_find(struct unit_test_state *uts) ut_assert(dev); } - ret = uclass_find_first_device(UCLASS_TEST_DUMMY, &dev); - ut_assert(ret == -ENODEV); + ut_assertok(uclass_find_first_device(UCLASS_TEST_DUMMY, &dev)); ut_assert(!dev); return 0; From e5f739045890eef2e97488c9c2a7d036ab908e58 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:56 -0600 Subject: [PATCH 49/95] dm: core: Add device_foreach_child() We have a 'safe' version of this function but sometimes it is not needed. Add a normal version too and update a few places that can use it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/arm/mach-uniphier/pinctrl-glue.c | 4 ++-- drivers/block/blk-uclass.c | 4 ++-- include/dm/device.h | 9 +++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-uniphier/pinctrl-glue.c b/arch/arm/mach-uniphier/pinctrl-glue.c index c4d3b17c39..b45f72f59a 100644 --- a/arch/arm/mach-uniphier/pinctrl-glue.c +++ b/arch/arm/mach-uniphier/pinctrl-glue.c @@ -13,14 +13,14 @@ int uniphier_pin_init(const char *pinconfig_name) { - struct udevice *pctldev, *config, *next; + struct udevice *pctldev, *config; int ret; ret = uclass_first_device(UCLASS_PINCTRL, &pctldev); if (ret) return ret; - device_foreach_child_safe(config, next, pctldev) { + device_foreach_child(config, pctldev) { if (strcmp(config->name, pinconfig_name)) continue; diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index baaf431e5e..e8f58b3f5e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -142,9 +142,9 @@ struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) */ struct blk_desc *blk_get_by_device(struct udevice *dev) { - struct udevice *child_dev, *next; + struct udevice *child_dev; - device_foreach_child_safe(child_dev, next, dev) { + device_foreach_child(child_dev, dev) { if (device_get_uclass_id(child_dev) != UCLASS_BLK) continue; diff --git a/include/dm/device.h b/include/dm/device.h index 27a6d7b9fd..d1210429e9 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -679,6 +679,15 @@ static inline bool device_is_on_pci_bus(struct udevice *dev) #define device_foreach_child_safe(pos, next, parent) \ list_for_each_entry_safe(pos, next, &parent->child_head, sibling_node) +/** + * device_foreach_child() - iterate through child devices + * + * @pos: struct udevice * for the current device + * @parent: parent device to scan + */ +#define device_foreach_child(pos, parent) \ + list_for_each_entry(pos, &parent->child_head, sibling_node) + /** * dm_scan_fdt_dev() - Bind child device in a the device tree * From 22327003a9d23c25044ce411e2daa992c835763c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:57 -0600 Subject: [PATCH 50/95] dm: test: Correct a stray backslash in dm_test_destroy() This should perhaps be a period. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: add the ending period and reword the commit message] Signed-off-by: Bin Meng --- test/dm/test-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dm/test-main.c b/test/dm/test-main.c index 74f77ccc84..72648162a9 100644 --- a/test/dm/test-main.c +++ b/test/dm/test-main.c @@ -64,7 +64,7 @@ static int dm_test_destroy(struct unit_test_state *uts) /* * If the uclass doesn't exist we don't want to create it. So - * check that here before we call uclass_find_device()/ + * check that here before we call uclass_find_device(). */ uc = uclass_find(id); if (!uc) From a605b0f76791b0ec0d7f1703b07ad876c12be1b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:55:59 -0600 Subject: [PATCH 51/95] sandbox: spmi: Add ranges property for address translation At present address translation does not work since there is no ranges property in the spmi nodes. Add empty ranges properties and a little more logging so that this shows the error: /tmp/b/sandbox/u-boot -d /tmp/b/sandbox/arch/sandbox/dts/test.dtb \ -c "ut dm spmi_access_peripheral" -L7 -v ... pm8916_gpio_probe() bad address: returning err=-22 Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/sandbox/dts/test.dts | 2 ++ drivers/gpio/pm8916_gpio.c | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 27b0baab27..50d245ae91 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -713,11 +713,13 @@ compatible = "sandbox,spmi"; #address-cells = <0x1>; #size-cells = <0x1>; + ranges; pm8916@0 { compatible = "qcom,spmi-pmic"; reg = <0x0 0x1>; #address-cells = <0x1>; #size-cells = <0x1>; + ranges; spmi_gpios: gpios@c000 { compatible = "qcom,pm8916-gpio"; diff --git a/drivers/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c index bbe214d5ee..74a773c099 100644 --- a/drivers/gpio/pm8916_gpio.c +++ b/drivers/gpio/pm8916_gpio.c @@ -172,16 +172,16 @@ static int pm8916_gpio_probe(struct udevice *dev) priv->pid = dev_read_addr(dev); if (priv->pid == FDT_ADDR_T_NONE) - return -EINVAL; + return log_msg_ret("bad address", -EINVAL); /* Do a sanity check */ reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); if (reg != 0x10) - return -ENODEV; + return log_msg_ret("bad type", -ENXIO); reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE); if (reg != 0x5 && reg != 0x1) - return -ENODEV; + return log_msg_ret("bad subtype", -ENXIO); return 0; } @@ -257,16 +257,16 @@ static int pm8941_pwrkey_probe(struct udevice *dev) priv->pid = devfdt_get_addr(dev); if (priv->pid == FDT_ADDR_T_NONE) - return -EINVAL; + return log_msg_ret("bad address", -EINVAL); /* Do a sanity check */ reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); if (reg != 0x1) - return -ENODEV; + return log_msg_ret("bad type", -ENXIO); reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE); if (reg != 0x1) - return -ENODEV; + return log_msg_ret("bad subtype", -ENXIO); return 0; } From 5abd58f0de66955f14e37da49e9d2d3e2f92ef88 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:00 -0600 Subject: [PATCH 52/95] sandbox: mmc: Fix up MMC emulator for valgrind At present running sandbox with valgrind produces some warnings due to the MMC emulator not filling in all the expected fields. Fix it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: use sizeof() instead of hardcoded 16] Signed-off-by: Bin Meng --- drivers/mmc/sandbox_mmc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 2fa7d8c3dc..899952d773 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -27,6 +27,7 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, { switch (cmd->cmdidx) { case MMC_CMD_ALL_SEND_CID: + memset(cmd->response, '\0', sizeof(cmd->response)); break; case SD_CMD_SEND_RELATIVE_ADDR: cmd->response[0] = 0 << 16; /* mmc->rca */ @@ -43,11 +44,14 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, case MMC_CMD_SEND_CSD: cmd->response[0] = 0; cmd->response[1] = 10 << 16; /* 1 << block_len */ + cmd->response[2] = 0; + cmd->response[3] = 0; break; case SD_CMD_SWITCH_FUNC: { if (!data) break; u32 *resp = (u32 *)data->dest; + resp[3] = 0; resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY); if ((cmd->cmdarg & 0xF) == UHS_SDR12_BUS_SPEED) resp[4] = (cmd->cmdarg & 0xF) << 24; From 3414581380d9dace84ac6347aa1b448d12ba900d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:01 -0600 Subject: [PATCH 53/95] sandbox: Rename PCI ID for swap_case to be more specific Rename this ID to SANDBOX_PCI_SWAP_CASE_EMUL_ID since it is more descriptive and allows us to add new PCI emulators without any conflict or confusion. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/include/asm/test.h | 2 +- drivers/misc/swap_case.c | 5 +++-- test/dm/pci.c | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index cbf209693d..1b21af6bed 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -12,7 +12,7 @@ #define SANDBOX_I2C_TEST_ADDR 0x59 #define SANDBOX_PCI_VENDOR_ID 0x1234 -#define SANDBOX_PCI_DEVICE_ID 0x5678 +#define SANDBOX_PCI_SWAP_CASE_EMUL_ID 0x5678 #define SANDBOX_PCI_CLASS_CODE PCI_CLASS_CODE_COMM #define SANDBOX_PCI_CLASS_SUB_CODE PCI_CLASS_SUB_CODE_COMM_SERIAL diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c index 6afc6d9466..eb32d101f9 100644 --- a/drivers/misc/swap_case.c +++ b/drivers/misc/swap_case.c @@ -129,7 +129,7 @@ static int sandbox_swap_case_read_config(struct udevice *emul, uint offset, *valuep = SANDBOX_PCI_VENDOR_ID; break; case PCI_DEVICE_ID: - *valuep = SANDBOX_PCI_DEVICE_ID; + *valuep = SANDBOX_PCI_SWAP_CASE_EMUL_ID; break; case PCI_CLASS_DEVICE: if (size == PCI_SIZE_8) { @@ -417,7 +417,8 @@ U_BOOT_DRIVER(sandbox_swap_case_emul) = { }; static struct pci_device_id sandbox_swap_case_supported[] = { - { PCI_VDEVICE(SANDBOX, SANDBOX_PCI_DEVICE_ID), SWAP_CASE_DRV_DATA }, + { PCI_VDEVICE(SANDBOX, SANDBOX_PCI_SWAP_CASE_EMUL_ID), + SWAP_CASE_DRV_DATA }, {}, }; diff --git a/test/dm/pci.c b/test/dm/pci.c index c325f6600e..e70b65aea4 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -38,7 +38,7 @@ static int dm_test_pci_busdev(struct unit_test_state *uts) ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap)); device = 0; ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device)); - ut_asserteq(SANDBOX_PCI_DEVICE_ID, device); + ut_asserteq(SANDBOX_PCI_SWAP_CASE_EMUL_ID, device); /* Test bus#1 and its devices */ ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus)); @@ -50,7 +50,7 @@ static int dm_test_pci_busdev(struct unit_test_state *uts) ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x0c, 0), &swap)); device = 0; ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device)); - ut_asserteq(SANDBOX_PCI_DEVICE_ID, device); + ut_asserteq(SANDBOX_PCI_SWAP_CASE_EMUL_ID, device); return 0; } @@ -170,7 +170,7 @@ static int dm_test_pci_mixed(struct unit_test_state *uts) ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(2, 0x1f, 0), &swap)); device = 0; ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device)); - ut_asserteq(SANDBOX_PCI_DEVICE_ID, device); + ut_asserteq(SANDBOX_PCI_SWAP_CASE_EMUL_ID, device); /* First test I/O */ io_addr = dm_pci_read_bar32(swap, 0); From 239cdcff5a5df19e69ee2a97f5540a82678cbec7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:02 -0600 Subject: [PATCH 54/95] sandbox: Add support for clrsetio_32() and friends These functions are available on x86 but not sandbox. They are useful shortcuts and clarify the code, so add them to sandbox. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/include/asm/io.h | 42 ++++++++++++++++++++++++++++++----- arch/sandbox/lib/pci_io.c | 12 +++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index 2a350a826c..481787b516 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -110,13 +110,21 @@ phys_addr_t map_to_sysmem(const void *ptr); #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) /* I/O access functions */ -int inl(unsigned int addr); -int inw(unsigned int addr); -int inb(unsigned int addr); +int _inl(unsigned int addr); +int _inw(unsigned int addr); +int _inb(unsigned int addr); -void outl(unsigned int value, unsigned int addr); -void outw(unsigned int value, unsigned int addr); -void outb(unsigned int value, unsigned int addr); +void _outl(unsigned int value, unsigned int addr); +void _outw(unsigned int value, unsigned int addr); +void _outb(unsigned int value, unsigned int addr); + +#define inb(port) _inb((uintptr_t)(port)) +#define inw(port) _inw((uintptr_t)(port)) +#define inl(port) _inl((uintptr_t)(port)) + +#define outb(val, port) _outb(val, (uintptr_t)(port)) +#define outw(val, port) _outw(val, (uintptr_t)(port)) +#define outl(val, port) _outl(val, (uintptr_t)(port)) #define out_arch(type,endian,a,v) write##type(cpu_to_##endian(v),a) #define in_arch(type,endian,a) endian##_to_cpu(read##type(a)) @@ -188,6 +196,28 @@ static inline void memcpy_toio(volatile void *dst, const void *src, int count) #define insw(port, buf, ns) _insw((u16 *)port, buf, ns) #define outsw(port, buf, ns) _outsw((u16 *)port, buf, ns) +/* IO space accessors */ +#define clrio(type, addr, clear) \ + out##type(in##type(addr) & ~(clear), (addr)) + +#define setio(type, addr, set) \ + out##type(in##type(addr) | (set), (addr)) + +#define clrsetio(type, addr, clear, set) \ + out##type((in##type(addr) & ~(clear)) | (set), (addr)) + +#define clrio_32(addr, clear) clrio(l, addr, clear) +#define clrio_16(addr, clear) clrio(w, addr, clear) +#define clrio_8(addr, clear) clrio(b, addr, clear) + +#define setio_32(addr, set) setio(l, addr, set) +#define setio_16(addr, set) setio(w, addr, set) +#define setio_8(addr, set) setio(b, addr, set) + +#define clrsetio_32(addr, clear, set) clrsetio(l, addr, clear, set) +#define clrsetio_16(addr, clear, set) clrsetio(w, addr, clear, set) +#define clrsetio_8(addr, clear, set) clrsetio(b, addr, clear, set) + #include #include diff --git a/arch/sandbox/lib/pci_io.c b/arch/sandbox/lib/pci_io.c index 01822c6069..f22e47c7f6 100644 --- a/arch/sandbox/lib/pci_io.c +++ b/arch/sandbox/lib/pci_io.c @@ -91,7 +91,7 @@ static int pci_io_write(unsigned int addr, ulong value, pci_size_t size) return -ENOSYS; } -int inl(unsigned int addr) +int _inl(unsigned int addr) { unsigned long value; int ret; @@ -101,7 +101,7 @@ int inl(unsigned int addr) return ret ? 0 : value; } -int inw(unsigned int addr) +int _inw(unsigned int addr) { unsigned long value; int ret; @@ -111,7 +111,7 @@ int inw(unsigned int addr) return ret ? 0 : value; } -int inb(unsigned int addr) +int _inb(unsigned int addr) { unsigned long value; int ret; @@ -121,17 +121,17 @@ int inb(unsigned int addr) return ret ? 0 : value; } -void outl(unsigned int value, unsigned int addr) +void _outl(unsigned int value, unsigned int addr) { pci_io_write(addr, value, PCI_SIZE_32); } -void outw(unsigned int value, unsigned int addr) +void _outw(unsigned int value, unsigned int addr) { pci_io_write(addr, value, PCI_SIZE_16); } -void outb(unsigned int value, unsigned int addr) +void _outb(unsigned int value, unsigned int addr) { pci_io_write(addr, value, PCI_SIZE_8); } From cea7c0956ac2134e67f9d93bd96b2f2b4b85b430 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:03 -0600 Subject: [PATCH 55/95] sandbox: swap_case: Use statics where possible Some functions and a struct should be marked static since they are not used outside this file. Update them. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/misc/swap_case.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c index eb32d101f9..8abf88a8ff 100644 --- a/drivers/misc/swap_case.c +++ b/drivers/misc/swap_case.c @@ -286,8 +286,8 @@ static void sandbox_swap_case_do_op(enum swap_case_op op, char *str, int len) } } -int sandbox_swap_case_read_io(struct udevice *dev, unsigned int addr, - ulong *valuep, enum pci_size_t size) +static int sandbox_swap_case_read_io(struct udevice *dev, unsigned int addr, + ulong *valuep, enum pci_size_t size) { struct swap_case_priv *priv = dev_get_priv(dev); unsigned int offset; @@ -304,8 +304,8 @@ int sandbox_swap_case_read_io(struct udevice *dev, unsigned int addr, return 0; } -int sandbox_swap_case_write_io(struct udevice *dev, unsigned int addr, - ulong value, enum pci_size_t size) +static int sandbox_swap_case_write_io(struct udevice *dev, unsigned int addr, + ulong value, enum pci_size_t size) { struct swap_case_priv *priv = dev_get_priv(dev); unsigned int offset; @@ -392,7 +392,7 @@ static int sandbox_swap_case_unmap_physmem(struct udevice *dev, return 0; } -struct dm_pci_emul_ops sandbox_swap_case_emul_ops = { +static struct dm_pci_emul_ops sandbox_swap_case_emul_ops = { .get_devfn = sandbox_swap_case_get_devfn, .read_config = sandbox_swap_case_read_config, .write_config = sandbox_swap_case_write_config, From fae2c16ede7bf00c8f7873a96fc2b34d5345d751 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:04 -0600 Subject: [PATCH 56/95] sandbox: pci: Drop the get_devfn() method This method is not used anymore since the bus/device/function of PCI devices can be obtained from their (parent's per-child) platform data. Drop it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/misc/swap_case.c | 8 -------- include/pci.h | 7 ------- 2 files changed, 15 deletions(-) diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c index 8abf88a8ff..18d756e9cd 100644 --- a/drivers/misc/swap_case.c +++ b/drivers/misc/swap_case.c @@ -54,13 +54,6 @@ struct swap_case_priv { char mem_text[MEM_TEXT_SIZE]; }; -static int sandbox_swap_case_get_devfn(struct udevice *dev) -{ - struct pci_child_platdata *plat = dev_get_parent_platdata(dev); - - return plat->devfn; -} - static int sandbox_swap_case_use_ea(struct udevice *dev) { return !!ofnode_get_property(dev->node, "use-ea", NULL); @@ -393,7 +386,6 @@ static int sandbox_swap_case_unmap_physmem(struct udevice *dev, } static struct dm_pci_emul_ops sandbox_swap_case_emul_ops = { - .get_devfn = sandbox_swap_case_get_devfn, .read_config = sandbox_swap_case_read_config, .write_config = sandbox_swap_case_write_config, .read_io = sandbox_swap_case_read_io, diff --git a/include/pci.h b/include/pci.h index 298d0d4355..999a594cdd 100644 --- a/include/pci.h +++ b/include/pci.h @@ -1490,13 +1490,6 @@ int dm_pci_find_class(uint find_class, int index, struct udevice **devp); * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops { - /** - * get_devfn(): Check which device and function this emulators - * - * @dev: device to check - * @return the device and function this emulates, or -ve on error - */ - int (*get_devfn)(struct udevice *dev); /** * read_config() - Read a PCI configuration value * From 37a1cf9c9c4c670e074feb8fb2fc6b4a40a80b1b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:06 -0600 Subject: [PATCH 57/95] sandbox: pci: Move pci_offset_to_barnum() to pci.h This function is useful in PCI emulators. More it into the header file to avoid duplicating it in other drivers. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/misc/swap_case.c | 7 ++----- include/pci.h | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c index 18d756e9cd..75fe641670 100644 --- a/drivers/misc/swap_case.c +++ b/drivers/misc/swap_case.c @@ -24,9 +24,6 @@ struct swap_case_platdata { u32 bar[6]; }; -#define offset_to_barnum(offset) \ - (((offset) - PCI_BASE_ADDRESS_0) / sizeof(u32)) - enum { MEM_TEXT_SIZE = 0x100, }; @@ -144,7 +141,7 @@ static int sandbox_swap_case_read_config(struct udevice *emul, uint offset, int barnum; u32 *bar, result; - barnum = offset_to_barnum(offset); + barnum = pci_offset_to_barnum(offset); bar = &plat->bar[barnum]; result = *bar; @@ -224,7 +221,7 @@ static int sandbox_swap_case_write_config(struct udevice *emul, uint offset, int barnum; u32 *bar; - barnum = offset_to_barnum(offset); + barnum = pci_offset_to_barnum(offset); bar = &plat->bar[barnum]; debug("w bar %d=%lx\n", barnum, value); diff --git a/include/pci.h b/include/pci.h index 999a594cdd..2b82b2c5a3 100644 --- a/include/pci.h +++ b/include/pci.h @@ -215,6 +215,10 @@ #define PCI_BASE_ADDRESS_IO_MASK (~0x03ULL) /* bit 1 is reserved if address_space = 1 */ +/* Convert a regsister address (e.g. PCI_BASE_ADDRESS_1) to a bar # (e.g. 1) */ +#define pci_offset_to_barnum(offset) \ + (((offset) - PCI_BASE_ADDRESS_0) / sizeof(u32)) + /* Header type 0 (normal devices) */ #define PCI_CARDBUS_CIS 0x28 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c From 189882c9337bd4fa0a6b2c5de3031cd6f4b8e262 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:07 -0600 Subject: [PATCH 58/95] sandbox: Add a -T flag to use the test device tree U-Boot already supports using -D to indicate that it should use the normal device tree. It is sometimes useful to run with the test device tree, e.g. when running a test. Add a -T option for this along with some documentation. It can be used like this: /tmp/b/sandbox/u-boot -T -c "ut dm pci_busdev" (this will use /tmp/b/sandbox/arch/sandbox/dts/test.dtb as the DT) Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/sandbox/cpu/start.c | 25 +++++++++++++++++++++++++ doc/arch/sandbox.rst | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 82828f0c1d..cfc542c806 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -147,6 +147,31 @@ static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state, SANDBOX_CMDLINE_OPT_SHORT(default_fdt, 'D', 0, "Use the default u-boot.dtb control FDT in U-Boot directory"); +static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, + const char *arg) +{ + const char *fmt = "/arch/sandbox/dts/test.dtb"; + char *p; + char *fname; + int len; + + len = strlen(state->argv[0]) + strlen(fmt) + 1; + fname = os_malloc(len); + if (!fname) + return -ENOMEM; + strcpy(fname, state->argv[0]); + p = strrchr(fname, '/'); + if (!p) + p = fname + strlen(fname); + len -= p - fname; + snprintf(p, len, fmt, p); + state->fdt_fname = fname; + + return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(test_fdt, 'T', 0, + "Use the test.dtb control FDT in U-Boot directory"); + static int sandbox_cmdline_cb_interactive(struct sandbox_state *state, const char *arg) { diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst index 5c0caebcbf..54933b5675 100644 --- a/doc/arch/sandbox.rst +++ b/doc/arch/sandbox.rst @@ -103,6 +103,8 @@ A device tree binary file can be provided with -d. If you edit the source (it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to recreate the binary file. +To use the default device tree, use -D. To use the test device tree, use -T. + To execute commands directly, use the -c option. You can specify a single command, or multiple commands separated by a semicolon, as is normal in U-Boot. Be careful with quoting as the shell will normally process and @@ -499,6 +501,13 @@ run natively on your board if desired (and enabled). To run all tests use "make check". +To run a single test in an existing sandbox build, you can use -T to use the +test device tree, and -c to select the test: + + /tmp/b/sandbox/u-boot -T -c "ut dm pci_busdev" + +This runs dm_test_pci_busdev() which is in test/dm/pci.c + Memory Map ---------- From b0e2c23d3ea7786492178302758712e498bba380 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:08 -0600 Subject: [PATCH 59/95] sandbox: pci: Increase the memory space Increase the memory space so we can support the p2sb bus which needs multiples of 1MB. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/dts/test.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 50d245ae91..5e859ba11d 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -447,7 +447,7 @@ device_type = "pci"; #address-cells = <3>; #size-cells = <2>; - ranges = <0x02000000 0 0x10000000 0x10000000 0 0x2000 + ranges = <0x02000000 0 0x10000000 0x10000000 0 0x2000000 0x01000000 0 0x20000000 0x20000000 0 0x2000>; pci@0,0 { compatible = "pci-generic"; From e77663cf747b4c01fc72e3af1c72996a0f586613 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:09 -0600 Subject: [PATCH 60/95] sandbox: Allow use of real I/O with readl(), etc. At present these functions are stubbed out. For more comprehensive testing with PCI devices it is useful to be able to fully emulate I/O access. Add simple implementations for these. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: change to use 'const void *' in sandbox_write(); cast 'addr' in read/write macros in arch/sandbox/include/asm/io.h; remove the unnecessary cast in readq/writeq in nvme.h] Signed-off-by: Bin Meng --- arch/sandbox/cpu/cpu.c | 52 ++++++++++++++++++++++++++++++++ arch/sandbox/include/asm/io.h | 28 +++++++++++------ arch/sandbox/include/asm/state.h | 1 + 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index fdfb209f77..2046cb53c4 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -225,6 +225,58 @@ phys_addr_t map_to_sysmem(const void *ptr) return mentry->tag; } +unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size) +{ + struct sandbox_state *state = state_get_current(); + + if (!state->allow_memio) + return 0; + + switch (size) { + case SB_SIZE_8: + return *(u8 *)addr; + case SB_SIZE_16: + return *(u16 *)addr; + case SB_SIZE_32: + return *(u32 *)addr; + case SB_SIZE_64: + return *(u64 *)addr; + } + + return 0; +} + +void sandbox_write(const void *addr, unsigned int val, + enum sandboxio_size_t size) +{ + struct sandbox_state *state = state_get_current(); + + if (!state->allow_memio) + return; + + switch (size) { + case SB_SIZE_8: + *(u8 *)addr = val; + break; + case SB_SIZE_16: + *(u16 *)addr = val; + break; + case SB_SIZE_32: + *(u32 *)addr = val; + break; + case SB_SIZE_64: + *(u64 *)addr = val; + break; + } +} + +void sandbox_set_enable_memio(bool enable) +{ + struct sandbox_state *state = state_get_current(); + + state->allow_memio = enable; +} + void sandbox_set_enable_pci_map(int enable) { enable_pci_map = enable; diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index 481787b516..4a35c41972 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -6,6 +6,13 @@ #ifndef __SANDBOX_ASM_IO_H #define __SANDBOX_ASM_IO_H +enum sandboxio_size_t { + SB_SIZE_8, + SB_SIZE_16, + SB_SIZE_32, + SB_SIZE_64, +}; + void *phys_to_virt(phys_addr_t paddr); #define phys_to_virt phys_to_virt @@ -38,18 +45,21 @@ static inline void unmap_sysmem(const void *vaddr) /* Map from a pointer to our RAM buffer */ phys_addr_t map_to_sysmem(const void *ptr); -/* Define nops for sandbox I/O access */ -#define readb(addr) ((void)addr, 0) -#define readw(addr) ((void)addr, 0) -#define readl(addr) ((void)addr, 0) +unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size); +void sandbox_write(const void *addr, unsigned int val, + enum sandboxio_size_t size); + +#define readb(addr) sandbox_read((const void *)addr, SB_SIZE_8) +#define readw(addr) sandbox_read((const void *)addr, SB_SIZE_16) +#define readl(addr) sandbox_read((const void *)addr, SB_SIZE_32) #ifdef CONFIG_SANDBOX64 -#define readq(addr) ((void)addr, 0) +#define readq(addr) sandbox_read((const void *)addr, SB_SIZE_64) #endif -#define writeb(v, addr) ((void)addr) -#define writew(v, addr) ((void)addr) -#define writel(v, addr) ((void)addr) +#define writeb(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_8) +#define writew(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_16) +#define writel(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_32) #ifdef CONFIG_SANDBOX64 -#define writeq(v, addr) ((void)addr) +#define writeq(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_64) #endif /* diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 2d773d3fa6..ad3e94beb9 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -102,6 +102,7 @@ struct sandbox_state { ulong next_tag; /* Next address tag to allocate */ struct list_head mapmem_head; /* struct sandbox_mapmem_entry */ bool hwspinlock; /* Hardware Spinlock status */ + bool allow_memio; /* Allow readl() etc. to work */ /* * This struct is getting large. From 9b69ba4a787209da59e69fd4e411ab6561b0447f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:10 -0600 Subject: [PATCH 61/95] pci: sandbox: Move the emulators into their own node Sandbox pci works using emulation drivers which are currently children of the pci device: pci-controller { pci@1f,0 { compatible = "pci-generic"; reg = <0xf800 0 0 0 0>; emul@1f,0 { compatible = "sandbox,swap-case"; }; }; }; In this case the emulation device is attached to pci device on address f800 (device 1f, function 0) and provides the swap-case functionality. However this is not ideal, since every device on a PCI bus has a child device. This is only really the case for sandbox, but we want to avoid special-case code for sandbox. Worse, child devices cannot be probed before their parents. This forces us to use 'find' rather than 'get' to obtain the emulator device. In fact the emulator devices are never probed. There is code in sandbox_pci_emul_post_probe() which tries to track when emulators are active, but at present this does not work. A better approach seems to be to add a separate node elsewhere in the device tree, an 'emulation parent'. This could be given a bogus address (such as -1) to hide the emulators away from the 'pci' command, but it seems better to keep it at the root node to avoid such hacks. Then we can use a phandle to point from the device to the correct emulator, and only on sandbox. The code to find an emulator does not interfere with normal pci operation. Add a new UCLASS_PCI_EMUL_PARENT uclass which allows finding an emulator given a bus, and finding a bus given an emulator. Update the existing device trees and the code for finding an emulator. This brings PCI emulators more into line with I2C. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: fix 3 typos in the commit message; encode bus number in the labels of swap_case_emul nodes; mention commit 4345998ae9df in sandbox_pci_get_emul()] Signed-off-by: Bin Meng --- arch/sandbox/dts/sandbox.dtsi | 11 +++++++--- arch/sandbox/dts/test.dts | 38 +++++++++++++++++++++++------------ doc/driver-model/pci-info.rst | 23 +++++++++++---------- drivers/pci/pci-emul-uclass.c | 36 +++++++++++++++++++++++++++------ include/dm/uclass-id.h | 1 + 5 files changed, 76 insertions(+), 33 deletions(-) diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index c6d5650c20..f09bc70b0d 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -103,9 +103,14 @@ pci@1f,0 { compatible = "pci-generic"; reg = <0xf800 0 0 0 0>; - emul@1f,0 { - compatible = "sandbox,swap-case"; - }; + sandbox,emul = <&swap_case_emul>; + }; + }; + + emul { + compatible = "sandbox,pci-emul-parent"; + swap_case_emul: emul@1f,0 { + compatible = "sandbox,swap-case"; }; }; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 5e859ba11d..b6d0960097 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -452,24 +452,31 @@ pci@0,0 { compatible = "pci-generic"; reg = <0x0000 0 0 0 0>; - emul@0,0 { - compatible = "sandbox,swap-case"; - }; + sandbox,emul = <&swap_case_emul0_0>; }; pci@1,0 { compatible = "pci-generic"; reg = <0x0800 0 0 0 0>; - emul@0,0 { - compatible = "sandbox,swap-case"; - use-ea; - }; + sandbox,emul = <&swap_case_emul0_1>; }; pci@1f,0 { compatible = "pci-generic"; reg = <0xf800 0 0 0 0>; - emul@1f,0 { - compatible = "sandbox,swap-case"; - }; + sandbox,emul = <&swap_case_emul0_1f>; + }; + }; + + pci-emul0 { + compatible = "sandbox,pci-emul-parent"; + swap_case_emul0_0: emul0@0,0 { + compatible = "sandbox,swap-case"; + }; + swap_case_emul0_1: emul0@1,0 { + compatible = "sandbox,swap-case"; + use-ea; + }; + swap_case_emul0_1f: emul0@1f,0 { + compatible = "sandbox,swap-case"; }; }; @@ -499,9 +506,14 @@ pci@1f,0 { compatible = "pci-generic"; reg = <0xf800 0 0 0 0>; - emul@1f,0 { - compatible = "sandbox,swap-case"; - }; + sandbox,emul = <&swap_case_emul2_1f>; + }; + }; + + pci-emul2 { + compatible = "sandbox,pci-emul-parent"; + swap_case_emul2_1f: emul2@1f,0 { + compatible = "sandbox,swap-case"; }; }; diff --git a/doc/driver-model/pci-info.rst b/doc/driver-model/pci-info.rst index d93ab8b61d..f39ff990a6 100644 --- a/doc/driver-model/pci-info.rst +++ b/doc/driver-model/pci-info.rst @@ -113,14 +113,17 @@ Sandbox ------- With sandbox we need a device emulator for each device on the bus since there -is no real PCI bus. This works by looking in the device tree node for a -driver. For example:: - +is no real PCI bus. This works by looking in the device tree node for an +emulator driver. For example:: pci@1f,0 { compatible = "pci-generic"; reg = <0xf800 0 0 0 0>; - emul@1f,0 { + sandbox,emul = <&emul_1f>; + }; + pci-emul { + compatible = "sandbox,pci-emul-parent"; + emul_1f: emul@1f,0 { compatible = "sandbox,swap-case"; }; }; @@ -130,14 +133,16 @@ Note that the first cell in the 'reg' value is the bus/device/function. See PCI_BDF() for the encoding (it is also specified in the IEEE Std 1275-1994 PCI bus binding document, v2.1) +The pci-emul node should go outside the pci bus node, since otherwise it will +be scanned as a PCI device, causing confusion. + When this bus is scanned we will end up with something like this:: `- * pci-controller @ 05c660c8, 0 `- pci@1f,0 @ 05c661c8, 63488 - `- emul@1f,0 @ 05c662c8 + `- emul@1f,0 @ 05c662c8 -When accesses go to the pci@1f,0 device they are forwarded to its child, the -emulator. +When accesses go to the pci@1f,0 device they are forwarded to its emulator. The sandbox PCI drivers also support dynamic driver binding, allowing device driver to declare the driver binding information via U_BOOT_PCI_DEVICE(), @@ -164,7 +169,3 @@ When this bus is scanned we will end up with something like this:: pci [ + ] pci_sandbo |-- pci-controller1 pci_emul [ ] sandbox_sw | |-- sandbox_swap_case_emul pci_emul [ ] sandbox_sw | `-- sandbox_swap_case_emul - -Note the difference from the statically declared device nodes is that the -device is directly attached to the host controller, instead of via a container -device like pci@1f,0. diff --git a/drivers/pci/pci-emul-uclass.c b/drivers/pci/pci-emul-uclass.c index 3822758354..6b4efcea37 100644 --- a/drivers/pci/pci-emul-uclass.c +++ b/drivers/pci/pci-emul-uclass.c @@ -10,6 +10,7 @@ #include #include #include +#include struct sandbox_pci_emul_priv { int dev_count; @@ -30,13 +31,14 @@ int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn, } *containerp = dev; - if (device_get_uclass_id(dev) == UCLASS_PCI_GENERIC) { - ret = device_find_first_child(dev, emulp); - if (ret) - return ret; - } else { + /* + * See commit 4345998ae9df, + * "pci: sandbox: Support dynamically binding device driver" + */ + ret = uclass_find_device_by_phandle(UCLASS_PCI_EMUL, dev, + "sandbox,emul", emulp); + if (ret && device_get_uclass_id(dev) != UCLASS_PCI_GENERIC) *emulp = dev; - } return *emulp ? 0 : -ENODEV; } @@ -68,3 +70,25 @@ UCLASS_DRIVER(pci_emul) = { .pre_remove = sandbox_pci_emul_pre_remove, .priv_auto_alloc_size = sizeof(struct sandbox_pci_emul_priv), }; + +/* + * This uclass is a child of the pci bus. Its platdata is not defined here so + * is defined by its parent, UCLASS_PCI, which uses struct pci_child_platdata. + * See per_child_platdata_auto_alloc_size in UCLASS_DRIVER(pci). + */ +UCLASS_DRIVER(pci_emul_parent) = { + .id = UCLASS_PCI_EMUL_PARENT, + .name = "pci_emul_parent", + .post_bind = dm_scan_fdt_dev, +}; + +static const struct udevice_id pci_emul_parent_ids[] = { + { .compatible = "sandbox,pci-emul-parent" }, + { } +}; + +U_BOOT_DRIVER(pci_emul_parent_drv) = { + .name = "pci_emul_parent_drv", + .id = UCLASS_PCI_EMUL_PARENT, + .of_match = pci_emul_parent_ids, +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index d4d96106b3..f431f3bf29 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -23,6 +23,7 @@ enum uclass_id { UCLASS_I2C_EMUL, /* sandbox I2C device emulator */ UCLASS_I2C_EMUL_PARENT, /* parent for I2C device emulators */ UCLASS_PCI_EMUL, /* sandbox PCI device emulator */ + UCLASS_PCI_EMUL_PARENT, /* parent for PCI device emulators */ UCLASS_USB_EMUL, /* sandbox USB bus device emulator */ UCLASS_AXI_EMUL, /* sandbox AXI bus device emulator */ From be0d8fa452a4b6ed09a4228980052c35ef7331e0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 31 Aug 2019 17:59:32 -0600 Subject: [PATCH 62/95] pci: sandbox: Probe PCI emulation devices when used At present PCI emulation devices are not probed before use, since they used to be children of the device that used them, and children cannot be probed before their parents. Now that PCI emulation devices are attached to the root node, we can simply probe them, and avoid using the internal function. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: rebase the patch against u-boot-x86/next to get it applied cleanly] Signed-off-by: Bin Meng --- drivers/pci/pci-emul-uclass.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci-emul-uclass.c b/drivers/pci/pci-emul-uclass.c index 6b4efcea37..fd87b3ea4e 100644 --- a/drivers/pci/pci-emul-uclass.c +++ b/drivers/pci/pci-emul-uclass.c @@ -10,7 +10,6 @@ #include #include #include -#include struct sandbox_pci_emul_priv { int dev_count; @@ -35,8 +34,8 @@ int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn, * See commit 4345998ae9df, * "pci: sandbox: Support dynamically binding device driver" */ - ret = uclass_find_device_by_phandle(UCLASS_PCI_EMUL, dev, - "sandbox,emul", emulp); + ret = uclass_get_device_by_phandle(UCLASS_PCI_EMUL, dev, "sandbox,emul", + emulp); if (ret && device_get_uclass_id(dev) != UCLASS_PCI_GENERIC) *emulp = dev; From 0911569b285c82dcda166c46d689bc561272995c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:12 -0600 Subject: [PATCH 63/95] pci: Show the result of binding a device Update the debugging info a little to show the result of trying to bind a PCI device. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci-uclass.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index ab3e1310eb..4c84c65685 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -790,7 +790,7 @@ int pci_bind_bus_devices(struct udevice *bus) if (!PCI_FUNC(bdf)) found_multi = header_type & 0x80; - debug("%s: bus %d/%s: found device %x, function %d\n", __func__, + debug("%s: bus %d/%s: found device %x, function %d", __func__, bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf)); pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device, PCI_SIZE_16); @@ -800,6 +800,7 @@ int pci_bind_bus_devices(struct udevice *bus) /* Find this device in the device tree */ ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); + debug(": find ret=%d\n", ret); /* If nothing in the device tree, bind a device */ if (ret == -ENODEV) { From 90c668605fa81ab5046a8b05c7a1fa858811d4bf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:13 -0600 Subject: [PATCH 64/95] pci: Disable autoconfig in SPL At present U-Boot runs autoconfig in SPL but this is best left to U-Boot proper. For TPL and SPL we can normally used fixed BARs and save code size and time. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 4c84c65685..896cb6b23a 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -983,7 +983,7 @@ static int pci_uclass_post_probe(struct udevice *bus) if (ret) return ret; -#ifdef CONFIG_PCI_PNP +#if CONFIG_IS_ENABLED(PCI_PNP) ret = pci_auto_config_devices(bus); if (ret < 0) return ret; From bdaa976153b29c88822e6c196e48f6ad2f881846 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:14 -0600 Subject: [PATCH 65/95] pci: Correct 'specifified' and 'Plese' typos Fix these spelling errors the header file and documentation. Fix a small typo in the PCI documentation. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- doc/driver-model/pci-info.rst | 2 +- include/pci.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/driver-model/pci-info.rst b/doc/driver-model/pci-info.rst index f39ff990a6..3c1b1adf07 100644 --- a/doc/driver-model/pci-info.rst +++ b/doc/driver-model/pci-info.rst @@ -103,7 +103,7 @@ in each of these nodes. If PCI devices are not listed in the device tree, U_BOOT_PCI_DEVICE can be used to specify the driver to use for the device. The device tree takes precedence -over U_BOOT_PCI_DEVICE. Plese note with U_BOOT_PCI_DEVICE, only drivers with +over U_BOOT_PCI_DEVICE. Please note with U_BOOT_PCI_DEVICE, only drivers with DM_FLAG_PRE_RELOC will be bound before relocation. If neither device tree nor U_BOOT_PCI_DEVICE is provided, the built-in driver (either pci_bridge_drv or pci_generic_drv) will be used. diff --git a/include/pci.h b/include/pci.h index 2b82b2c5a3..8aa6636cfb 100644 --- a/include/pci.h +++ b/include/pci.h @@ -1595,7 +1595,7 @@ int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn, /** * pci_get_devfn() - Extract the devfn from fdt_pci_addr of the device * - * Get devfn from fdt_pci_addr of the specifified device + * Get devfn from fdt_pci_addr of the specified device * * @dev: PCI device * @return devfn in bits 15...8 if found, -ENODEV if not found From f365152a55e6619d5f87d851790e329f7b441b61 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:15 -0600 Subject: [PATCH 66/95] pci: Add more debug detail when resources are exhausted If PCI auto-config runs out of memory, show a few more details to help diagnose the problem. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: change %x to %llx to avoid build warnings on some platforms] Signed-off-by: Bin Meng --- drivers/pci/pci_auto_common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci_auto_common.c b/drivers/pci/pci_auto_common.c index 84908e6154..8690316610 100644 --- a/drivers/pci/pci_auto_common.c +++ b/drivers/pci/pci_auto_common.c @@ -45,7 +45,9 @@ int pciauto_region_allocate(struct pci_region *res, pci_size_t size, addr = ((res->bus_lower - 1) | (size - 1)) + 1; if (addr - res->bus_start + size > res->size) { - debug("No room in resource"); + debug("No room in resource, avail start=%llx / size=%llx, " + "need=%llx\n", (unsigned long long)res->bus_lower, + (unsigned long long)res->size, (unsigned long long)size); goto error; } From 6a73cf3d8fe32f3bddd4ba7dd47dcb75df5ca592 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:16 -0600 Subject: [PATCH 67/95] pci: Show a message if PCI autoconfig fails At present this fails silently which can be confusing since some devices on the PCI bus may not work correctly. Show a message in this case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: add a '\n' in the PCI autoconfig fail message] Signed-off-by: Bin Meng --- drivers/pci/pci_auto.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 1a3bf70834..28667bde8d 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -39,6 +39,8 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) { + int ret = 0; + /* Tickle the BAR and get the response */ if (!enum_only) dm_pci_write_config32(dev, bar, 0xffffffff); @@ -97,9 +99,13 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, (unsigned long long)bar_size); } - if (!enum_only && pciauto_region_allocate(bar_res, bar_size, - &bar_value, - found_mem64) == 0) { + if (!enum_only) { + ret = pciauto_region_allocate(bar_res, bar_size, + &bar_value, found_mem64); + if (ret) + printf("PCI: Failed autoconfig bar %x\n", bar); + } + if (!enum_only && !ret) { /* Write it out and update our limit */ dm_pci_write_config32(dev, bar, (u32)bar_value); From 33c215af4b9de32e5052bb716411dc34ce9b63ac Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 15 Sep 2019 12:08:58 -0600 Subject: [PATCH 68/95] dm: pci: Add a function to read a PCI BAR At present PCI address transaction is not supported so drivers must manually read the correct BAR after reading the device tree info. The ns16550 has a suitable implementation, so move this code into the core DM support. Note that there is no live-tree equivalent at present. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: correct the unclear comments in test.dts] Signed-off-by: Bin Meng --- arch/sandbox/dts/test.dts | 7 ++++-- drivers/core/fdtaddr.c | 33 ++++++++++++++++++++++++++++ drivers/core/read.c | 11 ++++++++++ drivers/serial/ns16550.c | 31 +-------------------------- include/dm/fdtaddr.h | 8 +++++++ include/dm/read.h | 25 ++++++++++++++++++++++ test/dm/pci.c | 45 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 128 insertions(+), 32 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index b6d0960097..25cac056bb 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -456,12 +456,15 @@ }; pci@1,0 { compatible = "pci-generic"; - reg = <0x0800 0 0 0 0>; + /* reg 0 is at 0x14, using FDT_PCI_SPACE_MEM32 */ + reg = <0x02000814 0 0 0 0 + 0x01000810 0 0 0 0>; sandbox,emul = <&swap_case_emul0_1>; }; pci@1f,0 { compatible = "pci-generic"; - reg = <0xf800 0 0 0 0>; + /* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */ + reg = <0x0100f810 0 0 0 0>; sandbox,emul = <&swap_case_emul0_1f>; }; }; diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index 6850003a28..c9a941116a 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -190,3 +190,36 @@ void *devfdt_map_physmem(struct udevice *dev, unsigned long size) return map_physmem(addr, size, MAP_NOCACHE); } + +fdt_addr_t devfdt_get_addr_pci(struct udevice *dev) +{ + ulong addr; + + addr = devfdt_get_addr(dev); + if (CONFIG_IS_ENABLED(PCI) && IS_ENABLED(CONFIG_DM_PCI) && + addr == FDT_ADDR_T_NONE) { + struct fdt_pci_addr pci_addr; + u32 bar; + int ret; + + ret = fdtdec_get_pci_addr(gd->fdt_blob, + dev_of_offset(dev), + FDT_PCI_SPACE_MEM32, "reg", + &pci_addr); + if (ret) { + /* try if there is any i/o-mapped register */ + ret = fdtdec_get_pci_addr(gd->fdt_blob, + dev_of_offset(dev), + FDT_PCI_SPACE_IO, "reg", + &pci_addr); + if (ret) + return FDT_ADDR_T_NONE; + } + ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar); + if (ret) + return FDT_ADDR_T_NONE; + addr = bar; + } + + return addr; +} diff --git a/drivers/core/read.c b/drivers/core/read.c index fb3dcd9a79..9602e52d1b 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -307,3 +307,14 @@ int dev_read_alias_highest_id(const char *stem) return fdtdec_get_alias_highest_id(gd->fdt_blob, stem); } + +fdt_addr_t dev_read_addr_pci(struct udevice *dev) +{ + ulong addr; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE && !of_live_active()) + addr = devfdt_get_addr_pci(dev); + + return addr; +} diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 01f334938e..754b6e9921 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -440,36 +440,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) int err; /* try Processor Local Bus device first */ - addr = dev_read_addr(dev); -#if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI) - if (addr == FDT_ADDR_T_NONE) { - /* then try pci device */ - struct fdt_pci_addr pci_addr; - u32 bar; - int ret; - - /* we prefer to use a memory-mapped register */ - ret = fdtdec_get_pci_addr(gd->fdt_blob, dev_of_offset(dev), - FDT_PCI_SPACE_MEM32, "reg", - &pci_addr); - if (ret) { - /* try if there is any i/o-mapped register */ - ret = fdtdec_get_pci_addr(gd->fdt_blob, - dev_of_offset(dev), - FDT_PCI_SPACE_IO, - "reg", &pci_addr); - if (ret) - return ret; - } - - ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar); - if (ret) - return ret; - - addr = bar; - } -#endif - + addr = dev_read_addr_pci(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h index 57b326cb33..959d3bc2d6 100644 --- a/include/dm/fdtaddr.h +++ b/include/dm/fdtaddr.h @@ -138,4 +138,12 @@ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name); fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name, fdt_size_t *size); +/** + * devfdt_get_addr_pci() - Read an address and handle PCI address translation + * + * @dev: Device to read from + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t devfdt_get_addr_pci(struct udevice *dev); + #endif diff --git a/include/dm/read.h b/include/dm/read.h index 803daf7620..d37fcb504d 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -248,6 +248,26 @@ fdt_addr_t dev_read_addr(struct udevice *dev); */ void *dev_read_addr_ptr(struct udevice *dev); +/** + * dev_read_addr_pci() - Read an address and handle PCI address translation + * + * At present U-Boot does not have address translation logic for PCI in the + * livetree implementation (of_addr.c). This special function supports this for + * the flat tree implementation. + * + * This function should be removed (and code should use dev_read() instead) + * once: + * + * 1. PCI address translation is added; and either + * 2. everything uses livetree where PCI translation is used (which is feasible + * in SPL and U-Boot proper) or PCI address translation is added to + * fdtdec_get_addr() and friends. + * + * @dev: Device to read from + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_pci(struct udevice *dev); + /** * dev_remap_addr() - Get the reg property of a device as a * memory-mapped I/O pointer @@ -691,6 +711,11 @@ static inline void *dev_read_addr_ptr(struct udevice *dev) return devfdt_get_addr_ptr(dev); } +static inline fdt_addr_t dev_read_addr_pci(struct udevice *dev) +{ + return devfdt_get_addr_pci(dev); +} + static inline void *dev_remap_addr(struct udevice *dev) { return devfdt_remap_addr(dev); diff --git a/test/dm/pci.c b/test/dm/pci.c index e70b65aea4..fb93e4c78a 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -294,3 +294,48 @@ static int dm_test_pci_ea(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_pci_ea, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test the dev_read_addr_pci() function */ +static int dm_test_pci_addr_flat(struct unit_test_state *uts) +{ + struct udevice *swap1f, *swap1; + ulong io_addr, mem_addr; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); + io_addr = dm_pci_read_bar32(swap1f, 0); + ut_asserteq(io_addr, dev_read_addr_pci(swap1f)); + + /* + * This device has both I/O and MEM spaces but the MEM space appears + * first + */ + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); + mem_addr = dm_pci_read_bar32(swap1, 1); + ut_asserteq(mem_addr, dev_read_addr_pci(swap1)); + + return 0; +} +DM_TEST(dm_test_pci_addr_flat, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | + DM_TESTF_FLAT_TREE); + +/* + * Test the dev_read_addr_pci() function with livetree. That function is + * not currently fully implemented, in that it fails to return the BAR address. + * Once that is implemented this test can be removed and dm_test_pci_addr_flat() + * can be used for both flattree and livetree by removing the DM_TESTF_FLAT_TREE + * flag above. + */ +static int dm_test_pci_addr_live(struct unit_test_state *uts) +{ + struct udevice *swap1f, *swap1; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); + ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); + ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); + + return 0; +} +DM_TEST(dm_test_pci_addr_live, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | + DM_TESTF_LIVE_TREE); From 4e8de068a3b210c0fea2b29372b25c60c7b6dc9e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:18 -0600 Subject: [PATCH 69/95] serial: ns16550: Add a PCI device/function field When this UART is used early in boot (before PCI is set up) it is convenient to store the PCI BDF of the UART so that it can be manually configured. This is useful when it is used as a debug UART, for example. Add a new field to hold this information, so that drivers can simply use the existing platform data. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/ns16550.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/ns16550.h b/include/ns16550.h index 22b89e4d6d..701efeea85 100644 --- a/include/ns16550.h +++ b/include/ns16550.h @@ -52,6 +52,7 @@ * @reg_width: IO accesses size of registers (in bytes) * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) * @clock: UART base clock speed in Hz + * @bdf: PCI slot/function (pci_dev_t) */ struct ns16550_platdata { unsigned long base; @@ -60,6 +61,9 @@ struct ns16550_platdata { int reg_offset; int clock; u32 fcr; +#if defined(CONFIG_PCI) && defined(CONFIG_SPL) + int bdf; +#endif }; struct udevice; From 7bc4f0f88327bcd3c2daafe969f049dcfab41b00 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 15 Sep 2019 18:10:36 -0600 Subject: [PATCH 70/95] binman: Allow verbose output with all commands At present the verbose flag only works for the 'build' command. This is not intended, nor is it useful. Update the code to support the verbose flag and make use of a command exception handler. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: rebase the patch against u-boot-x86/next to get it applied cleanly] Signed-off-by: Bin Meng --- tools/binman/control.py | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/tools/binman/control.py b/tools/binman/control.py index 9e7587864c..cb51bc2dd4 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -468,29 +468,23 @@ def Binman(args): command.Run(pager, fname) return 0 - if args.cmd == 'ls': + if args.cmd in ['ls', 'extract', 'replace']: try: + tout.Init(args.verbosity) tools.PrepareOutputDir(None) - ListEntries(args.image, args.paths) - finally: - tools.FinaliseOutputDir() - return 0 + if args.cmd == 'ls': + ListEntries(args.image, args.paths) - if args.cmd == 'extract': - try: - tools.PrepareOutputDir(None) - ExtractEntries(args.image, args.filename, args.outdir, args.paths, - not args.uncompressed) - finally: - tools.FinaliseOutputDir() - return 0 + if args.cmd == 'extract': + ExtractEntries(args.image, args.filename, args.outdir, args.paths, + not args.uncompressed) - if args.cmd == 'replace': - try: - tools.PrepareOutputDir(None) - ReplaceEntries(args.image, args.filename, args.indir, args.paths, - do_compress=not args.compressed, - allow_resize=not args.fix_size, write_map=args.map) + if args.cmd == 'replace': + ReplaceEntries(args.image, args.filename, args.indir, args.paths, + do_compress=not args.compressed, + allow_resize=not args.fix_size, write_map=args.map) + except: + raise finally: tools.FinaliseOutputDir() return 0 From 4e185e8dd7aa3ff7618d228ebfaffb507a569c07 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:20 -0600 Subject: [PATCH 71/95] binman: Add a base implementation of Entry.ReadChildData() At present this function is not present in the Entry base class so it is hard to find the documentation for it. Move the docs from the section class and expand it a little. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- tools/binman/entry.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 6a2c6e0d92..f2f1b967a4 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -717,6 +717,22 @@ features to produce new behaviours. data = self.section.ReadChildData(self, decomp) return data + def ReadChildData(self, child, decomp=True): + """Read the data for a particular child + + This reads data from the parent and extracts the piece that relates to + the given child. + + Args: + child: Child to read (must be valid) + decomp: True to decompress any compressed data before returning it; + False to return the raw, uncompressed data + + Returns: + Data for the child (bytes) + """ + pass + def LoadData(self, decomp=True): data = self.ReadData(decomp) self.contents_size = len(data) From 2d553c006d46653f3e0367cc5bfe36a9c7128eb5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:21 -0600 Subject: [PATCH 72/95] binman: Handle reading data for end-at-4gb sections Some x86 sections have special offsets which currently result in empty data being returned from the 'extract' command. Fix this by taking account of the skip-at-start property. Add a little more debugging while we are here. Signed-off-by: Simon Glass Acked-by: Bin Meng --- tools/binman/entry.py | 6 ++++-- tools/binman/etype/section.py | 16 +++++----------- tools/binman/image.py | 2 ++ 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tools/binman/entry.py b/tools/binman/entry.py index f2f1b967a4..fe8e1dd8a5 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -714,17 +714,19 @@ features to produce new behaviours. """ # Use True here so that we get an uncompressed section to work from, # although compressed sections are currently not supported + tout.Debug("ReadChildData section '%s', entry '%s'" % + (self.section.GetPath(), self.GetPath())) data = self.section.ReadChildData(self, decomp) return data def ReadChildData(self, child, decomp=True): - """Read the data for a particular child + """Read the data for a particular child entry This reads data from the parent and extracts the piece that relates to the given child. Args: - child: Child to read (must be valid) + child: Child entry to read data for (must be valid) decomp: True to decompress any compressed data before returning it; False to return the raw, uncompressed data diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 5d34fc546a..8179daf562 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -500,18 +500,12 @@ class Entry_section(Entry): return data def ReadChildData(self, child, decomp=True): - """Read the data for a particular child entry - - Args: - child: Child entry to read data for - decomp: True to return uncompressed data, False to leave the data - compressed if it is compressed - - Returns: - Data contents of entry - """ + tout.Debug("ReadChildData for child '%s'" % child.GetPath()) parent_data = self.ReadData(True) - data = parent_data[child.offset:child.offset + child.size] + offset = child.offset - self._skip_at_start + tout.Debug("Extract for child '%s': offset %#x, skip_at_start %#x, result %#x" % + (child.GetPath(), child.offset, self._skip_at_start, offset)) + data = parent_data[offset:offset + child.size] if decomp: indata = data data = tools.Decompress(indata, child.compress) diff --git a/tools/binman/image.py b/tools/binman/image.py index 7b39a1ddce..2beab7fd4d 100644 --- a/tools/binman/image.py +++ b/tools/binman/image.py @@ -201,6 +201,8 @@ class Image(section.Entry_section): return entry def ReadData(self, decomp=True): + tout.Debug("Image '%s' ReadData(), size=%#x" % + (self.GetPath(), len(self._data))) return self._data def GetListEntries(self, entry_paths): From 0b7ebee38e5d9167360bc756fcfb72af8badc74f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:22 -0600 Subject: [PATCH 73/95] binman: Take account of skip-at-start with image-header The image-header currently sets it offset assuming that skip-at-start is zero. This does not work on x86 where offsets end at 4GB. Add in this value so that the offset is correct. Signed-off-by: Simon Glass Acked-by: Bin Meng --- tools/binman/etype/image_header.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binman/etype/image_header.py b/tools/binman/etype/image_header.py index 4b69eda1a2..b9327dd799 100644 --- a/tools/binman/etype/image_header.py +++ b/tools/binman/etype/image_header.py @@ -100,6 +100,7 @@ class Entry_image_header(Entry): offset = offset else: offset = image_size - IMAGE_HEADER_LEN + offset += self.section.GetStartOffset() return Entry.Pack(self, offset) def ProcessContents(self): From fd42948fc9868207573992eaabf4f3e8144a3d1e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:23 -0600 Subject: [PATCH 74/95] log: Add log_nop() to avoid unused-variable warnings If a log statement includes a variable and logging is disabled, this can generate warnings about unused variables. Add a bit more complexity to the macros to avoid this for the common case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/log.h | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/include/log.h b/include/log.h index 6d15e955d7..d8f18a6afd 100644 --- a/include/log.h +++ b/include/log.h @@ -76,6 +76,18 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, int line, const char *func, const char *fmt, ...) __attribute__ ((format (__printf__, 6, 7))); +static inline int _log_nop(enum log_category_t cat, enum log_level_t level, + const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__ ((format (__printf__, 6, 7))); + +static inline int _log_nop(enum log_category_t cat, enum log_level_t level, + const char *file, int line, const char *func, + const char *fmt, ...) +{ + return 0; +} + /* Define this at the top of a file to add a prefix to debug messages */ #ifndef pr_fmt #define pr_fmt(fmt) fmt @@ -101,13 +113,14 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, #define log_io(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt) #else #define _LOG_MAX_LEVEL LOGL_INFO -#define log_err(_fmt...) -#define log_warning(_fmt...) -#define log_notice(_fmt...) -#define log_info(_fmt...) -#define log_debug(_fmt...) -#define log_content(_fmt...) -#define log_io(_fmt...) +#define log_err(_fmt...) log_nop(LOG_CATEGORY, LOGL_ERR, ##_fmt) +#define log_warning(_fmt...) log_nop(LOG_CATEGORY, LOGL_WARNING, ##_fmt) +#define log_notice(_fmt...) log_nop(LOG_CATEGORY, LOGL_NOTICE, ##_fmt) +#define log_info(_fmt...) log_nop(LOG_CATEGORY, LOGL_INFO, ##_fmt) +#define log_debug(_fmt...) log_nop(LOG_CATEGORY, LOGL_DEBUG, ##_fmt) +#define log_content(_fmt...) log_nop(LOG_CATEGORY, \ + LOGL_DEBUG_CONTENT, ##_fmt) +#define log_io(_fmt...) log_nop(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt) #endif #if CONFIG_IS_ENABLED(LOG) @@ -129,6 +142,12 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, #define log(_cat, _level, _fmt, _args...) #endif +#define log_nop(_cat, _level, _fmt, _args...) ({ \ + int _l = _level; \ + _log_nop((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \ + __func__, pr_fmt(_fmt), ##_args); \ +}) + #ifdef DEBUG #define _DEBUG 1 #else From e37d963ec80351e51c3b0832d9306bd91b1dafbf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:24 -0600 Subject: [PATCH 75/95] cros_ec: Add MEC_EMI_BASE and size to the header file Provide these values which are part of the EC interface now. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/ec_commands.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/ec_commands.h b/include/ec_commands.h index 392c1f1a43..444ba61e59 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -71,6 +71,10 @@ #define EC_LPC_CMDR_SCI (1 << 5) /* SCI event is pending */ #define EC_LPC_CMDR_SMI (1 << 6) /* SMI event is pending */ +/* MEC uses 0x800/0x804 as register/index pair, thus an 8-byte resource */ +#define MEC_EMI_BASE 0x800 +#define MEC_EMI_SIZE 8 + #define EC_LPC_ADDR_MEMMAP 0x900 #define EC_MEMMAP_SIZE 255 /* ACPI IO buffer max is 255 bytes */ #define EC_MEMMAP_TEXT_MAX 8 /* Size of a string in the memory map */ From 9da3776bf6d782be47edcc8f15b89d1ffbd33724 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:25 -0600 Subject: [PATCH 76/95] iod: Enhance to support display of multiple values At present the 'iod' command differs from 'md' in that it only shows a single value. It is useful to see a dump of multiple values, particularly when x86 peripherals contain register sets accessible via I/O ports. Enhance the command to match md. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: correct multi-line comment format style] Signed-off-by: Bin Meng --- cmd/io.c | 77 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/cmd/io.c b/cmd/io.c index 79faf814ff..7fee9674a2 100644 --- a/cmd/io.c +++ b/cmd/io.c @@ -11,6 +11,13 @@ #include #include +/* Display values from last command */ +static ulong last_addr, last_size; +static ulong last_length = 0x40; +static ulong base_address; + +#define DISP_LINE_LEN 16 + /* * IO Display * @@ -19,26 +26,66 @@ */ int do_io_iod(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - ulong addr; - int size; + ulong addr, length, bytes; + u8 buf[DISP_LINE_LEN]; + int size, todo; - if (argc != 2) + /* + * We use the last specified parameters, unless new ones are + * entered. + */ + addr = last_addr; + size = last_size; + length = last_length; + + if (argc < 2) return CMD_RET_USAGE; - size = cmd_get_data_size(argv[0], 4); - if (size < 0) - return 1; + if ((flag & CMD_FLAG_REPEAT) == 0) { + /* + * New command specified. Check for a size specification. + * Defaults to long if no or incorrect specification. + */ + size = cmd_get_data_size(argv[0], 4); + if (size < 0) + return 1; - addr = simple_strtoul(argv[1], NULL, 16); + /* Address is specified since argc > 1 */ + addr = simple_strtoul(argv[1], NULL, 16); + addr += base_address; - printf("%04x: ", (u16) addr); + /* + * If another parameter, it is the length to display. + * Length is the number of objects, not number of bytes. + */ + if (argc > 2) + length = simple_strtoul(argv[2], NULL, 16); + } - if (size == 4) - printf("%08x\n", inl(addr)); - else if (size == 2) - printf("%04x\n", inw(addr)); - else - printf("%02x\n", inb(addr)); + bytes = size * length; + + /* Print the lines */ + for (; bytes > 0; addr += todo) { + u8 *ptr = buf; + int i; + + todo = min(bytes, (ulong)DISP_LINE_LEN); + for (i = 0; i < todo; i += size, ptr += size) { + if (size == 4) + *(u32 *)ptr = inl(addr + i); + else if (size == 2) + *(u16 *)ptr = inw(addr + i); + else + *ptr = inb(addr + i); + } + print_buffer(addr, buf, size, todo / size, + DISP_LINE_LEN / size); + bytes -= todo; + } + + last_addr = addr; + last_length = length; + last_size = size; return 0; } @@ -69,7 +116,7 @@ int do_io_iow(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) } /**************************************************/ -U_BOOT_CMD(iod, 2, 0, do_io_iod, +U_BOOT_CMD(iod, 3, 1, do_io_iod, "IO space display", "[.b, .w, .l] address"); U_BOOT_CMD(iow, 3, 0, do_io_iow, From 535e07846af6d05eece6e51e4c7b53239d3ac8ba Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:26 -0600 Subject: [PATCH 77/95] arm: mxs: Correct CONFIG_SPL_NO_CPU_SUPPORT option At present this is defined in Kconfig but there is a separate one in the CONFIG whitelist. It looks like these are duplicates. Rename the non-Kconfig one and remove it from the whitelist. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/arm/cpu/arm926ejs/Makefile | 2 +- include/configs/mxs.h | 2 +- scripts/config_whitelist.txt | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile index fdb0c926fb..b051025bb0 100644 --- a/arch/arm/cpu/arm926ejs/Makefile +++ b/arch/arm/cpu/arm926ejs/Makefile @@ -7,7 +7,7 @@ extra-y = start.o obj-y = cpu.o cache.o ifdef CONFIG_SPL_BUILD -ifdef CONFIG_SPL_NO_CPU_SUPPORT_CODE +ifdef CONFIG_SPL_NO_CPU_SUPPORT extra-y := endif endif diff --git a/include/configs/mxs.h b/include/configs/mxs.h index 6cadd720d2..e079f8035b 100644 --- a/include/configs/mxs.h +++ b/include/configs/mxs.h @@ -45,7 +45,7 @@ /* SPL */ #ifndef CONFIG_SPL_FRAMEWORK -#define CONFIG_SPL_NO_CPU_SUPPORT_CODE +#define CONFIG_SPL_NO_CPU_SUPPORT #define CONFIG_SPL_START_S_PATH "arch/arm/cpu/arm926ejs/mxs" #endif diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 5a007d3709..cb855354ae 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1721,7 +1721,6 @@ CONFIG_SPL_NAND_MINIMAL CONFIG_SPL_NAND_RAW_ONLY CONFIG_SPL_NAND_SOFTECC CONFIG_SPL_NAND_WORKSPACE -CONFIG_SPL_NO_CPU_SUPPORT_CODE CONFIG_SPL_PAD_TO CONFIG_SPL_PANIC_ON_RAW_IMAGE CONFIG_SPL_PBL_PAD From 27084c03d36a7f0e4d7c1679761e81567f1d5442 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:27 -0600 Subject: [PATCH 78/95] spl: Allow tiny printf() to be controlled in SPL and TPL At present there is only one control for this and it is used for both SPL and TPL. But SPL might have a lot more space than TPL so the extra cost of a full printf() might be acceptable. Split the option into two, providing separate SPL and TPL controls. The TPL setting defaults to the same as SPL. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/arm/Kconfig | 2 +- arch/arm/mach-omap2/Kconfig | 6 +++--- arch/arm/mach-rmobile/Kconfig | 2 +- arch/arm/mach-rmobile/Kconfig.32 | 14 ++++++------- arch/arm/mach-socfpga/Kconfig | 4 ++-- common/spl/Kconfig | 2 +- common/xyzModem.c | 2 +- configs/am335x_pdu001_defconfig | 2 +- configs/ls1043ardb_nand_SECURE_BOOT_defconfig | 2 +- configs/ls1043ardb_nand_defconfig | 2 +- .../ls1043ardb_sdcard_SECURE_BOOT_defconfig | 2 +- configs/ls1043ardb_sdcard_defconfig | 2 +- configs/sandbox_spl_defconfig | 2 +- drivers/gpio/gpio-uclass.c | 4 ++-- drivers/mmc/mmc.c | 2 +- drivers/mtd/spi/sf-uclass.c | 2 +- lib/Kconfig | 20 +++++++++++++++---- lib/Makefile | 2 +- 18 files changed, 43 insertions(+), 31 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3b0e315061..7086db368f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -954,7 +954,7 @@ config ARCH_SUNXI select USB if DISTRO_DEFAULTS select USB_KEYBOARD if DISTRO_DEFAULTS select USB_STORAGE if DISTRO_DEFAULTS - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM imply CMD_GPT imply CMD_UBI if NAND diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index ed8056e871..4c87cbc00f 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -11,7 +11,7 @@ config OMAP34XX select ARM_ERRATA_454179 select ARM_ERRATA_621766 select ARM_ERRATA_725233 - select USE_TINY_PRINTF if SPL + select SPL_USE_TINY_PRINTF if SPL imply NAND_OMAP_GPMC imply SPL_FS_EXT4 imply SPL_FS_FAT @@ -31,7 +31,7 @@ config OMAP34XX config OMAP44XX bool "OMAP44XX SoC" - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply NAND_OMAP_ELM imply NAND_OMAP_GPMC imply SPL_DISPLAY_PRINT @@ -124,7 +124,7 @@ config AM33XX imply SPL_NAND_SUPPORT imply SYS_I2C_OMAP24XX imply SYS_THUMB_BUILD - imply USE_TINY_PRINTF + imply SPL_USE_TINY_PRINTF help Support for AM335x SOC from Texas Instruments. The AM335x high performance SOC features a Cortex-A8 diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 52ab891425..8343000c8f 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -32,7 +32,7 @@ config RCAR_GEN3 imply SPL_SYS_MALLOC_SIMPLE imply SPL_TINY_MEMSET imply SPL_YMODEM_SUPPORT - imply USE_TINY_PRINTF + imply SPL_USE_TINY_PRINTF config RZA1 prompt "Renesas ARM SoCs RZ/A1 (32bit)" diff --git a/arch/arm/mach-rmobile/Kconfig.32 b/arch/arm/mach-rmobile/Kconfig.32 index 1441c80692..d5e437f0d2 100644 --- a/arch/arm/mach-rmobile/Kconfig.32 +++ b/arch/arm/mach-rmobile/Kconfig.32 @@ -65,7 +65,7 @@ config TARGET_GOSE select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM config TARGET_KOELSCH @@ -74,7 +74,7 @@ config TARGET_KOELSCH select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM config TARGET_LAGER @@ -83,7 +83,7 @@ config TARGET_LAGER select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM config TARGET_KZM9G @@ -95,7 +95,7 @@ config TARGET_ALT select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM config TARGET_SILK @@ -104,7 +104,7 @@ config TARGET_SILK select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM config TARGET_PORTER @@ -113,7 +113,7 @@ config TARGET_PORTER select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM config TARGET_STOUT @@ -122,7 +122,7 @@ config TARGET_STOUT select DM_SERIAL select SPL_TINY_MEMSET select SUPPORT_SPL - select USE_TINY_PRINTF + select SPL_USE_TINY_PRINTF imply CMD_DM endchoice diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 1d914648e3..ee79953fcc 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -45,7 +45,7 @@ config TARGET_SOCFPGA_ARRIA10 select SPL_SYSCON if SPL select ETH_DESIGNWARE_SOCFPGA imply FPGA_SOCFPGA - imply USE_TINY_PRINTF + imply SPL_USE_TINY_PRINTF config TARGET_SOCFPGA_CYCLONE5 bool @@ -59,7 +59,7 @@ config TARGET_SOCFPGA_GEN5 imply SPL_SIZE_LIMIT_SUBTRACT_MALLOC imply SPL_STACK_R imply SPL_SYS_MALLOC_SIMPLE - imply USE_TINY_PRINTF + imply SPL_USE_TINY_PRINTF config TARGET_SOCFPGA_STRATIX10 bool diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 62b93c112b..048b85ba7a 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -963,7 +963,7 @@ config SPL_SERIAL_SUPPORT for displaying messages while SPL is running. It also brings in printf() and panic() functions. This should normally be enabled unless there are space reasons not to. Even then, consider - enabling USE_TINY_PRINTF which is a small printf() version. + enabling SPL_USE_TINY_PRINTF which is a small printf() version. config SPL_SPI_FLASH_SUPPORT bool "Support SPI flash drivers" diff --git a/common/xyzModem.c b/common/xyzModem.c index e85da74a69..6bf2375671 100644 --- a/common/xyzModem.c +++ b/common/xyzModem.c @@ -173,7 +173,7 @@ parse_num (char *s, unsigned long *val, char **es, char *delim) } -#if defined(DEBUG) && !defined(CONFIG_USE_TINY_PRINTF) +#if defined(DEBUG) && !CONFIG_IS_ENABLED(USE_TINY_PRINTF) /* * Note: this debug setup works by storing the strings in a fixed buffer */ diff --git a/configs/am335x_pdu001_defconfig b/configs/am335x_pdu001_defconfig index e69f81b6e5..1a1d58d3cc 100644 --- a/configs/am335x_pdu001_defconfig +++ b/configs/am335x_pdu001_defconfig @@ -51,5 +51,5 @@ CONFIG_SPL_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_TPS65910=y CONFIG_CONS_INDEX=4 -# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_SPL_USE_TINY_PRINTF is not set # CONFIG_EFI_LOADER is not set diff --git a/configs/ls1043ardb_nand_SECURE_BOOT_defconfig b/configs/ls1043ardb_nand_SECURE_BOOT_defconfig index 7aa8c54a12..c45fc68ac3 100644 --- a/configs/ls1043ardb_nand_SECURE_BOOT_defconfig +++ b/configs/ls1043ardb_nand_SECURE_BOOT_defconfig @@ -67,7 +67,7 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_RSA=y CONFIG_SPL_RSA=y CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/ls1043ardb_nand_defconfig b/configs/ls1043ardb_nand_defconfig index 22ccf526f6..a9e58047ac 100644 --- a/configs/ls1043ardb_nand_defconfig +++ b/configs/ls1043ardb_nand_defconfig @@ -67,5 +67,5 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig b/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig index 486a2e089b..bdfa13a0a7 100644 --- a/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig +++ b/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig @@ -65,7 +65,7 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_RSA=y CONFIG_SPL_RSA=y CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/ls1043ardb_sdcard_defconfig b/configs/ls1043ardb_sdcard_defconfig index b3c2970207..01adbf0b19 100644 --- a/configs/ls1043ardb_sdcard_defconfig +++ b/configs/ls1043ardb_sdcard_defconfig @@ -65,5 +65,5 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 0b3391a2a6..409b8a38d5 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -191,7 +191,7 @@ CONFIG_OSD=y CONFIG_SANDBOX_OSD=y CONFIG_FS_CBFS=y CONFIG_FS_CRAMFS=y -# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 01cfa2f788..90fbed455b 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -294,7 +294,7 @@ int dm_gpio_request(struct gpio_desc *desc, const char *label) static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) { -#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) +#if !defined(CONFIG_SPL_BUILD) || !CONFIG_IS_ENABLED(USE_TINY_PRINTF) va_list args; char buf[40]; @@ -343,7 +343,7 @@ int gpio_request(unsigned gpio, const char *label) */ int gpio_requestf(unsigned gpio, const char *fmt, ...) { -#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) +#if !defined(CONFIG_SPL_BUILD) || !CONFIG_IS_ENABLED(USE_TINY_PRINTF) va_list args; char buf[40]; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index c8f71cd0c1..6bece7f307 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -2577,7 +2577,7 @@ static int mmc_startup(struct mmc *mmc) bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len); #if !defined(CONFIG_SPL_BUILD) || \ (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \ - !defined(CONFIG_USE_TINY_PRINTF)) + !CONFIG_IS_ENABLED(USE_TINY_PRINTF)) sprintf(bdesc->vendor, "Man %06x Snr %04x%04x", mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff), (mmc->cid[3] >> 16) & 0xffff); diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23a..c6107522be 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -66,7 +66,7 @@ int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, char *str; int ret; -#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_USE_TINY_PRINTF) +#if defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(USE_TINY_PRINTF) str = "spi_flash"; #else char name[30]; diff --git a/lib/Kconfig b/lib/Kconfig index 3da45a5ec3..135f0b372b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -40,12 +40,12 @@ config PRINTF config SPL_PRINTF bool select SPL_SPRINTF - select SPL_STRTO if !USE_TINY_PRINTF + select SPL_STRTO if !SPL_USE_TINY_PRINTF config TPL_PRINTF bool select TPL_SPRINTF - select TPL_STRTO if !USE_TINY_PRINTF + select TPL_STRTO if !TPL_USE_TINY_PRINTF config SPRINTF bool @@ -95,9 +95,9 @@ config SYS_HZ get_timer() must operate in milliseconds and this option must be set to 1000. -config USE_TINY_PRINTF +config SPL_USE_TINY_PRINTF bool "Enable tiny printf() version" - depends on SPL || TPL + depends on SPL default y help This option enables a tiny, stripped down printf version. @@ -107,6 +107,18 @@ config USE_TINY_PRINTF The supported format specifiers are %c, %s, %u/%d and %x. +config TPL_USE_TINY_PRINTF + bool "Enable tiny printf() version" + depends on TPL + default y if SPL_USE_TINY_PRINTF + help + This option enables a tiny, stripped down printf version. + This should only be used in space limited environments, + like SPL versions with hard memory limits. This version + reduces the code size by about 2.5KiB on armv7. + + The supported format specifiers are %c, %s, %u/%d and %x. + config PANIC_HANG bool "Do not reset the system on fatal error" help diff --git a/lib/Makefile b/lib/Makefile index 2fffd68f94..d248d8626c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -106,7 +106,7 @@ obj-y += panic.o ifeq ($(CONFIG_$(SPL_TPL_)BUILD),y) # SPL U-Boot may use full-printf, tiny-printf or none at all -ifdef CONFIG_USE_TINY_PRINTF +ifdef CONFIG_$(SPL_TPL_)USE_TINY_PRINTF obj-$(CONFIG_$(SPL_TPL_)SPRINTF) += tiny-printf.o else obj-$(CONFIG_$(SPL_TPL_)SPRINTF) += vsprintf.o strmhz.o From b51882d0079d3275bdb83ce49fdc8a90133f7f07 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:28 -0600 Subject: [PATCH 79/95] spl: Convert CONFIG_SPL_SIZE_LIMIT to hex This is currently a decimal value which is not as convenient or meaningful. Also U-Boot tends to use hex everywhere. Convert this option to hex and add a comment for the size_check macro. Signed-off-by: Simon Glass Reviewed-by: Simon Goldschmidt Acked-by: Bin Meng [bmeng: correct the typo in the commit title] Signed-off-by: Bin Meng --- Makefile | 10 +++++++--- arch/arm/mach-socfpga/Kconfig | 2 +- common/spl/Kconfig | 2 +- configs/evb-rk3288_defconfig | 2 +- configs/tinker-rk3288_defconfig | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index b68cbaf437..3593039303 100644 --- a/Makefile +++ b/Makefile @@ -337,14 +337,18 @@ endif # KBUILD_MODULES := 1 #endif +# Check ths size of a binary: +# Args: +# $1: File to check +# #2: Size limit in bytes (decimal or 0xhex) define size_check actual=$$( wc -c $1 | awk '{print $$1}'); \ limit=$$( printf "%d" $2 ); \ if test $$actual -gt $$limit; then \ echo "$1 exceeds file size limit:" >&2; \ - echo " limit: $$limit bytes" >&2; \ - echo " actual: $$actual bytes" >&2; \ - echo " excess: $$((actual - limit)) bytes" >&2; \ + echo " limit: $$(printf %#x bytes $$limit) bytes" >&2; \ + echo " actual: $$(printf %#x $$actual) bytes" >&2; \ + echo " excess: $$(printf %#x $$((actual - limit))) bytes" >&2;\ exit 1; \ fi endef diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index ee79953fcc..45de153aa5 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -4,7 +4,7 @@ config NR_DRAM_BANKS default 1 config SPL_SIZE_LIMIT - default 65536 if TARGET_SOCFPGA_GEN5 + default 0x10000 if TARGET_SOCFPGA_GEN5 config SPL_SIZE_LIMIT_PROVIDE_STACK default 0x200 if TARGET_SOCFPGA_GEN5 diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 048b85ba7a..ef4fb19e52 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -26,7 +26,7 @@ config SPL_FRAMEWORK and the Linux Kernel. If unsure, say Y. config SPL_SIZE_LIMIT - int "Maximum size of SPL image" + hex "Maximum size of SPL image" depends on SPL default 69632 if ARCH_MX6 default 0 diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig index 7b0e908f71..043ee32bb4 100644 --- a/configs/evb-rk3288_defconfig +++ b/configs/evb-rk3288_defconfig @@ -4,7 +4,7 @@ CONFIG_SYS_TEXT_BASE=0x01000000 CONFIG_ROCKCHIP_RK3288=y CONFIG_TARGET_EVB_RK3288=y CONFIG_NR_DRAM_BANKS=1 -CONFIG_SPL_SIZE_LIMIT=307200 +CONFIG_SPL_SIZE_LIMIT=0x4b000 CONFIG_SPL_STACK_R_ADDR=0x80000 CONFIG_DEBUG_UART_BASE=0xff690000 CONFIG_DEBUG_UART_CLOCK=24000000 diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig index 9328608452..eff3b06b5c 100644 --- a/configs/tinker-rk3288_defconfig +++ b/configs/tinker-rk3288_defconfig @@ -5,7 +5,7 @@ CONFIG_SPL_GPIO_SUPPORT=y CONFIG_ROCKCHIP_RK3288=y CONFIG_TARGET_TINKER_RK3288=y CONFIG_NR_DRAM_BANKS=1 -CONFIG_SPL_SIZE_LIMIT=307200 +CONFIG_SPL_SIZE_LIMIT=0x4b000 CONFIG_SPL_STACK_R_ADDR=0x80000 CONFIG_DEBUG_UART_BASE=0xff690000 CONFIG_DEBUG_UART_CLOCK=24000000 From 59c871bca799e1dae0144192d936ac0a3c172686 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:30 -0600 Subject: [PATCH 80/95] spl: Allow distinguishing between two phases in U-Boot U-Boot has two distinct phases: before and after relocation. These are commonly referred to as F (running from Flash) and R (Relocated and running from RAM). Some drivers want to do different things in these phases so update the SPL phase function to return a different value for each. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/spl.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/spl.h b/include/spl.h index 9be8d0ddcf..c7cc2b0767 100644 --- a/include/spl.h +++ b/include/spl.h @@ -50,9 +50,10 @@ static inline bool u_boot_first_phase(void) } enum u_boot_phase { - PHASE_TPL, - PHASE_SPL, - PHASE_U_BOOT, + PHASE_TPL, /* Running in TPL */ + PHASE_SPL, /* Running in SPL */ + PHASE_BOARD_F, /* Running in U-Boot before relocation */ + PHASE_BOARD_R, /* Running in U-Boot after relocation */ }; /** @@ -92,7 +93,7 @@ enum u_boot_phase { * * but with this you can use: * - * if (spl_phase() == PHASE_U_BOOT) { + * if (spl_phase() == PHASE_BOARD_F) { * ... * } * @@ -105,7 +106,12 @@ static inline enum u_boot_phase spl_phase(void) #elif CONFIG_SPL_BUILD return PHASE_SPL; #else - return PHASE_U_BOOT; + DECLARE_GLOBAL_DATA_PTR; + + if (!(gd->flags & GD_FLG_RELOC)) + return PHASE_BOARD_F; + else + return PHASE_BOARD_R; #endif } From 49a0f8cc964c612164ef101267f90266279409a7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:32 -0600 Subject: [PATCH 81/95] x86: Move acpi_s3.h to a common location At present this hedaer is only available on x86. To allow sandbox to use it for testing, move it to a common location. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/baytrail/acpi.c | 2 +- arch/x86/cpu/cpu.c | 2 +- arch/x86/cpu/wakeup.S | 2 +- arch/x86/lib/acpi_s3.c | 2 +- arch/x86/lib/coreboot_table.c | 2 +- arch/x86/lib/fsp/fsp_common.c | 2 +- arch/x86/lib/fsp1/fsp_common.c | 2 +- drivers/pci/pci_rom.c | 2 +- drivers/sysreset/sysreset_x86.c | 2 +- {arch/x86/include/asm => include}/acpi_s3.h | 0 10 files changed, 9 insertions(+), 9 deletions(-) rename {arch/x86/include/asm => include}/acpi_s3.h (100%) diff --git a/arch/x86/cpu/baytrail/acpi.c b/arch/x86/cpu/baytrail/acpi.c index 1e3829a433..f44228e693 100644 --- a/arch/x86/cpu/baytrail/acpi.c +++ b/arch/x86/cpu/baytrail/acpi.c @@ -4,10 +4,10 @@ */ #include +#include #include #include #include -#include #include #include #include diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 290ee084e5..9ee4b0294a 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -19,13 +19,13 @@ */ #include +#include #include #include #include #include #include #include -#include #include #include #include diff --git a/arch/x86/cpu/wakeup.S b/arch/x86/cpu/wakeup.S index 663b02f27d..244ca1276a 100644 --- a/arch/x86/cpu/wakeup.S +++ b/arch/x86/cpu/wakeup.S @@ -5,7 +5,7 @@ * From coreboot src/arch/x86/wakeup.S */ -#include +#include #include #include diff --git a/arch/x86/lib/acpi_s3.c b/arch/x86/lib/acpi_s3.c index 03917188a9..197636c4b5 100644 --- a/arch/x86/lib/acpi_s3.c +++ b/arch/x86/lib/acpi_s3.c @@ -4,8 +4,8 @@ */ #include +#include #include -#include #include #include #include diff --git a/arch/x86/lib/coreboot_table.c b/arch/x86/lib/coreboot_table.c index 2d08a2db0d..8685aa3046 100644 --- a/arch/x86/lib/coreboot_table.c +++ b/arch/x86/lib/coreboot_table.c @@ -4,8 +4,8 @@ */ #include +#include #include -#include #include #include diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index 6678d75ffd..40ba866d77 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -4,10 +4,10 @@ */ #include +#include #include #include #include -#include #include #include #include diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index 285ef72ebf..e8066d8de3 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -4,10 +4,10 @@ */ #include +#include #include #include #include -#include #include #include #include diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 2cede1211b..1d4064e376 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -35,7 +35,7 @@ #include #ifdef CONFIG_X86 -#include +#include DECLARE_GLOBAL_DATA_PTR; #endif diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index 072f7948ef..8e2d1eaa7a 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -6,11 +6,11 @@ */ #include +#include #include #include #include #include -#include #include #include diff --git a/arch/x86/include/asm/acpi_s3.h b/include/acpi_s3.h similarity index 100% rename from arch/x86/include/asm/acpi_s3.h rename to include/acpi_s3.h From a827ba910cdbcae6d0a1c2ce7b91b41d00218a4c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 31 Aug 2019 21:23:18 -0600 Subject: [PATCH 82/95] x86: pci: Drop the first parameter in pci_x86_r/w_config() This parameter is needed by the PCI driver-mode interface but is always NULL on x86. There are a number of calls to this function so it makes sense to minimise the parameters. Adjust the x86 function to omit the first parameter, and introduce stub functions to handle the conversion. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: rebase the patch against u-boot-x86/next to get it applied cleanly] Signed-off-by: Bin Meng --- arch/x86/cpu/broadwell/cpu.c | 7 ++----- arch/x86/cpu/ivybridge/cpu.c | 3 +-- arch/x86/cpu/pci.c | 20 ++++++++------------ arch/x86/include/asm/pci.h | 15 ++++++--------- drivers/pci/pci_x86.c | 16 ++++++++++++++-- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index bba8cd1e94..297f1e0b68 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -103,11 +103,8 @@ int print_cpuinfo(void) void board_debug_uart_init(void) { - struct udevice *bus = NULL; - /* com1 / com2 decode range */ - pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16); + pci_x86_write_config(PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16); - pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN, - PCI_SIZE_16); + pci_x86_write_config(PCH_DEV_LPC, LPC_EN, COMA_LPC_EN, PCI_SIZE_16); } diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index c8b16e32c0..6db9da81b7 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -199,6 +199,5 @@ int print_cpuinfo(void) void board_debug_uart_init(void) { /* This enables the debug UART */ - pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN, - PCI_SIZE_16); + pci_x86_write_config(PCH_LPC_DEV, LPC_EN, COMA_LPC_EN, PCI_SIZE_16); } diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index 0ccde194d9..e1aae158ce 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -16,12 +16,8 @@ #include #include -/* - * TODO(sjg@chromium.org): Drop the first parameter from each of these - * functions since it is not used. - */ -int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, - ulong *valuep, enum pci_size_t size) +int pci_x86_read_config(pci_dev_t bdf, uint offset, ulong *valuep, + enum pci_size_t size) { outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR); switch (size) { @@ -39,8 +35,8 @@ int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, return 0; } -int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, - ulong value, enum pci_size_t size) +int pci_x86_write_config(pci_dev_t bdf, uint offset, ulong value, + enum pci_size_t size) { outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR); switch (size) { @@ -58,19 +54,19 @@ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, return 0; } -int pci_x86_clrset_config(struct udevice *bus, pci_dev_t bdf, uint offset, - ulong clr, ulong set, enum pci_size_t size) +int pci_x86_clrset_config(pci_dev_t bdf, uint offset, ulong clr, ulong set, + enum pci_size_t size) { ulong value; int ret; - ret = pci_x86_read_config(bus, bdf, offset, &value, size); + ret = pci_x86_read_config(bdf, offset, &value, size); if (ret) return ret; value &= ~clr; value |= set; - return pci_x86_write_config(bus, bdf, offset, value, size); + return pci_x86_write_config(bdf, offset, value, size); } void pci_assign_irqs(int bus, int device, u8 irq[4]) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index fb1edf3df7..2a72073572 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -22,30 +22,28 @@ * * This function can be called before PCI is set up in driver model. * - * @bus: Bus to read from (ignored, can be NULL) * @bdf: PCI device address: bus, device and function -see PCI_BDF() * @offset: Register offset to read * @valuep: Place to put the returned value * @size: Access size * @return 0 if OK, -ve on error */ -int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, - ulong *valuep, enum pci_size_t size); +int pci_x86_read_config(pci_dev_t bdf, uint offset, ulong *valuep, + enum pci_size_t size); /** * pci_bus_write_config() - Write a configuration value to a device * * This function can be called before PCI is set up in driver model. * - * @bus: Bus to read from (ignored, can be NULL) * @bdf: PCI device address: bus, device and function -see PCI_BDF() * @offset: Register offset to write * @value: Value to write * @size: Access size * @return 0 if OK, -ve on error */ -int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, - ulong value, enum pci_size_t size); +int pci_x86_write_config(pci_dev_t bdf, uint offset, ulong value, + enum pci_size_t size); /** * pci_bus_clrset_config32() - Update a configuration value for a device @@ -53,15 +51,14 @@ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, * The register at @offset is updated to (oldvalue & ~clr) | set. This function * can be called before PCI is set up in driver model. * - * @bus: Bus to read from (ignored, can be NULL) * @bdf: PCI device address: bus, device and function -see PCI_BDF() * @offset: Register offset to update * @clr: Bits to clear * @set: Bits to set * @return 0 if OK, -ve on error */ -int pci_x86_clrset_config(struct udevice *bus, pci_dev_t bdf, uint offset, - ulong clr, ulong set, enum pci_size_t size); +int pci_x86_clrset_config(pci_dev_t bdf, uint offset, ulong clr, ulong set, + enum pci_size_t size); /** * Assign IRQ number to a PCI device diff --git a/drivers/pci/pci_x86.c b/drivers/pci/pci_x86.c index 520ea4649e..e76a9c6e44 100644 --- a/drivers/pci/pci_x86.c +++ b/drivers/pci/pci_x86.c @@ -8,9 +8,21 @@ #include #include +static int _pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, + ulong *valuep, enum pci_size_t size) +{ + return pci_x86_read_config(bdf, offset, valuep, size); +} + +static int _pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, enum pci_size_t size) +{ + return pci_x86_write_config(bdf, offset, value, size); +} + static const struct dm_pci_ops pci_x86_ops = { - .read_config = pci_x86_read_config, - .write_config = pci_x86_write_config, + .read_config = _pci_x86_read_config, + .write_config = _pci_x86_write_config, }; static const struct udevice_id pci_x86_ids[] = { From e2493a7f5a06854d45175a4aa356ba3a2d810300 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:35 -0600 Subject: [PATCH 83/95] x86: Use a common definition of MSR_IA32_PERF_CTL Remove the duplicate definition as it is not needed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/broadwell/cpu.c | 2 +- arch/x86/cpu/broadwell/cpu_full.c | 2 +- arch/x86/cpu/intel_common/cpu.c | 2 +- arch/x86/include/asm/cpu_common.h | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index 297f1e0b68..61003a6d68 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -57,7 +57,7 @@ void set_max_freq(void) } perf_ctl.hi = 0; - msr_write(IA32_PERF_CTL, perf_ctl); + msr_write(MSR_IA32_PERF_CTL, perf_ctl); debug("CPU: frequency set to %d MHz\n", ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index 9686cf5e0e..0e3d878139 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -357,7 +357,7 @@ static void set_max_ratio(void) msr = msr_read(MSR_PLATFORM_INFO); perf_ctl.lo = msr.lo & 0xff00; } - msr_write(IA32_PERF_CTL, perf_ctl); + msr_write(MSR_IA32_PERF_CTL, perf_ctl); debug("cpu: frequency set to %d\n", ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index 9357626b5a..3a0d505a32 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -116,7 +116,7 @@ int cpu_intel_get_info(struct cpu_info *info, int bclk) { msr_t msr; - msr = msr_read(IA32_PERF_CTL); + msr = msr_read(MSR_IA32_PERF_CTL); info->cpu_freq = ((msr.lo >> 8) & 0xff) * bclk * 1000000; info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | 1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID; diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index 5e398bec94..7ae3bd1c53 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -6,8 +6,6 @@ #ifndef __ASM_CPU_COMMON_H #define __ASM_CPU_COMMON_H -#define IA32_PERF_CTL 0x199 - struct cpu_info; /** From 246ac08b037befab08805750049df75044ab7f6c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:36 -0600 Subject: [PATCH 84/95] x86: Add a common function to set CPU thermal target This code appears in a few places, so move it to a common file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/broadwell/cpu_full.c | 20 +------------------- arch/x86/cpu/intel_common/cpu.c | 22 ++++++++++++++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 25 +++---------------------- arch/x86/include/asm/cpu_common.h | 11 +++++++++++ 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index 0e3d878139..d1f3c07109 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -495,24 +495,6 @@ static void configure_misc(void) msr_write(MSR_IA32_PACKAGE_THERM_INTERRUPT, msr); } -static void configure_thermal_target(struct udevice *dev) -{ - int tcc_offset; - msr_t msr; - - tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "intel,tcc-offset", 0); - - /* Set TCC activaiton offset if supported */ - msr = msr_read(MSR_PLATFORM_INFO); - if ((msr.lo & (1 << 30)) && tcc_offset) { - msr = msr_read(MSR_TEMPERATURE_TARGET); - msr.lo &= ~(0xf << 24); /* Bits 27:24 */ - msr.lo |= (tcc_offset & 0xf) << 24; - msr_write(MSR_TEMPERATURE_TARGET, msr); - } -} - static void configure_dca_cap(void) { struct cpuid_result cpuid_regs; @@ -562,7 +544,7 @@ static void cpu_core_init(struct udevice *dev) configure_misc(); /* Thermal throttle activation offset */ - configure_thermal_target(dev); + cpu_configure_thermal_target(dev); /* Enable Direct Cache Access */ configure_dca_cap(); diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index 3a0d505a32..7d0ed73b4b 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -123,3 +123,25 @@ int cpu_intel_get_info(struct cpu_info *info, int bclk) return 0; } + +int cpu_configure_thermal_target(struct udevice *dev) +{ + u32 tcc_offset; + msr_t msr; + int ret; + + ret = dev_read_u32(dev, "tcc-offset", &tcc_offset); + if (!ret) + return -ENOENT; + + /* Set TCC activaiton offset if supported */ + msr = msr_read(MSR_PLATFORM_INFO); + if (msr.lo & (1 << 30)) { + msr = msr_read(MSR_TEMPERATURE_TARGET); + msr.lo &= ~(0xf << 24); /* Bits 27:24 */ + msr.lo |= (tcc_offset & 0xf) << 24; + msr_write(MSR_TEMPERATURE_TARGET, msr); + } + + return 0; +} diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 68e78e9478..ed66d2dd8d 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -283,26 +283,6 @@ static void configure_c_states(void) msr_write(MSR_PP1_CURRENT_CONFIG, msr); } -static int configure_thermal_target(struct udevice *dev) -{ - int tcc_offset; - msr_t msr; - - tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "tcc-offset", 0); - - /* Set TCC activaiton offset if supported */ - msr = msr_read(MSR_PLATFORM_INFO); - if ((msr.lo & (1 << 30)) && tcc_offset) { - msr = msr_read(MSR_TEMPERATURE_TARGET); - msr.lo &= ~(0xf << 24); /* Bits 27:24 */ - msr.lo |= (tcc_offset & 0xf) << 24; - msr_write(MSR_TEMPERATURE_TARGET, msr); - } - - return 0; -} - static void configure_misc(void) { msr_t msr; @@ -414,10 +394,11 @@ static int model_206ax_init(struct udevice *dev) configure_misc(); /* Thermal throttle activation offset */ - ret = configure_thermal_target(dev); + ret = cpu_configure_thermal_target(dev); if (ret) { debug("Cannot set thermal target\n"); - return ret; + if (ret != -ENOENT) + return ret; } /* Enable Direct Cache Access */ diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index 7ae3bd1c53..e158c96ce6 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -45,4 +45,15 @@ int cpu_set_flex_ratio_to_tdp_nominal(void); */ int cpu_intel_get_info(struct cpu_info *info, int bclk_mz); +/** + * cpu_configure_thermal_target() - Set the thermal target for a CPU + * + * This looks up the tcc-offset property and uses it to set the + * MSR_TEMPERATURE_TARGET value. + * + * @dev: CPU device + * @return 0 if OK, -ENOENT if no target is given in device tree + */ +int cpu_configure_thermal_target(struct udevice *dev); + #endif From 55a6b13a75276fbdf7186b34b4ad72238a7ec16b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:37 -0600 Subject: [PATCH 85/95] x86: Use a common bus clock for Intel CPUs Modern Intel CPUs use a standard bus clock value of 100MHz, so put this in a common file and tidy up the copies. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/broadwell/cpu.c | 2 +- arch/x86/cpu/broadwell/cpu_full.c | 4 ++-- arch/x86/cpu/ivybridge/model_206ax.c | 4 ++-- arch/x86/include/asm/arch-broadwell/cpu.h | 3 --- arch/x86/include/asm/arch-broadwell/pch.h | 3 --- arch/x86/include/asm/arch-ivybridge/model_206ax.h | 3 --- arch/x86/include/asm/cpu_common.h | 5 +++++ 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index 61003a6d68..586a2e8f05 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -60,7 +60,7 @@ void set_max_freq(void) msr_write(MSR_IA32_PERF_CTL, perf_ctl); debug("CPU: frequency set to %d MHz\n", - ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); + ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ); } int arch_cpu_init(void) diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index d1f3c07109..58cc2f362c 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -360,7 +360,7 @@ static void set_max_ratio(void) msr_write(MSR_IA32_PERF_CTL, perf_ctl); debug("cpu: frequency set to %d\n", - ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); + ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ); } int broadwell_init(struct udevice *dev) @@ -634,7 +634,7 @@ void cpu_set_power_limits(int power_limit_1_time) static int broadwell_get_info(struct udevice *dev, struct cpu_info *info) { - return cpu_intel_get_info(info, BROADWELL_BCLK); + return cpu_intel_get_info(info, INTEL_BCLK_MHZ); } static int broadwell_get_count(struct udevice *dev) diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index ed66d2dd8d..3177ba3297 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -346,7 +346,7 @@ static void set_max_ratio(void) msr_write(MSR_IA32_PERF_CTL, perf_ctl); debug("model_x06ax: frequency set to %d\n", - ((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK); + ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ); } static void set_energy_perf_bias(u8 policy) @@ -418,7 +418,7 @@ static int model_206ax_init(struct udevice *dev) static int model_206ax_get_info(struct udevice *dev, struct cpu_info *info) { - return cpu_intel_get_info(info, SANDYBRIDGE_BCLK); + return cpu_intel_get_info(info, INTEL_BCLK_MHZ); return 0; } diff --git a/arch/x86/include/asm/arch-broadwell/cpu.h b/arch/x86/include/asm/arch-broadwell/cpu.h index ca22a79996..3bc3bd6609 100644 --- a/arch/x86/include/asm/arch-broadwell/cpu.h +++ b/arch/x86/include/asm/arch-broadwell/cpu.h @@ -21,9 +21,6 @@ #define CPUID_BROADWELL_D0 0x306d3 #define CPUID_BROADWELL_E0 0x306d4 -/* Broadwell bus clock is fixed at 100MHz */ -#define BROADWELL_BCLK 100 - #define BROADWELL_FAMILY_ULT 0x306d0 #define CORE_THREAD_COUNT_MSR 0x35 diff --git a/arch/x86/include/asm/arch-broadwell/pch.h b/arch/x86/include/asm/arch-broadwell/pch.h index 23153a040f..ecdf6d16f9 100644 --- a/arch/x86/include/asm/arch-broadwell/pch.h +++ b/arch/x86/include/asm/arch-broadwell/pch.h @@ -6,9 +6,6 @@ #ifndef __ASM_ARCH_PCH_H #define __ASM_ARCH_PCH_H -/* CPU bus clock is fixed at 100MHz */ -#define CPU_BCLK 100 - #define PMBASE 0x40 #define ACPI_CNTL 0x44 #define ACPI_EN (1 << 7) diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h index 850d96bdd9..10caaa2422 100644 --- a/arch/x86/include/asm/arch-ivybridge/model_206ax.h +++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h @@ -8,9 +8,6 @@ #ifndef _ASM_ARCH_MODEL_206AX_H #define _ASM_ARCH_MODEL_206AX_H -/* SandyBridge/IvyBridge bus clock is fixed at 100MHz */ -#define SANDYBRIDGE_BCLK 100 - #define CPUID_VMX (1 << 5) #define CPUID_SMX (1 << 6) #define MSR_FEATURE_CONFIG 0x13c diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index e158c96ce6..f42eb32308 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -6,6 +6,11 @@ #ifndef __ASM_CPU_COMMON_H #define __ASM_CPU_COMMON_H +/* Standard Intel bus clock is fixed at 100MHz */ +enum { + INTEL_BCLK_MHZ = 100 +}; + struct cpu_info; /** From 2f0c2f03e71a68d7e5d8770c10d0154ead6dd104 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:38 -0600 Subject: [PATCH 86/95] x86: Add common functions for TDP and perf control These functions are the same on modern Intel CPUs, so use common code to set them. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: return false instead of 0 in cpu_ivybridge_config_tdp_levels(); fix 'muiltiplier' and 'desgn' typos] Signed-off-by: Bin Meng --- arch/x86/cpu/broadwell/cpu.c | 7 ++--- arch/x86/cpu/broadwell/cpu_full.c | 9 ------- arch/x86/cpu/intel_common/cpu.c | 20 ++++++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 27 +++++++------------ arch/x86/cpu/ivybridge/northbridge.c | 2 +- .../include/asm/arch-ivybridge/model_206ax.h | 2 +- arch/x86/include/asm/cpu_common.h | 18 +++++++++++++ 7 files changed, 52 insertions(+), 33 deletions(-) diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index 586a2e8f05..55a7439f1c 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -41,12 +41,9 @@ int arch_cpu_init_dm(void) void set_max_freq(void) { - msr_t msr, perf_ctl, platform_info; + msr_t msr, perf_ctl; - /* Check for configurable TDP option */ - platform_info = msr_read(MSR_PLATFORM_INFO); - - if ((platform_info.hi >> 1) & 3) { + if (cpu_config_tdp_levels()) { /* Set to nominal TDP ratio */ msr = msr_read(MSR_CONFIG_TDP_NOMINAL); perf_ctl.lo = (msr.lo & 0xff) << 8; diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index 58cc2f362c..169b5b02a6 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -329,15 +329,6 @@ static int bsp_init_before_ap_bringup(struct udevice *dev) return 0; } -static int cpu_config_tdp_levels(void) -{ - msr_t platform_info; - - /* Bits 34:33 indicate how many levels supported */ - platform_info = msr_read(MSR_PLATFORM_INFO); - return (platform_info.hi >> 1) & 3; -} - static void set_max_ratio(void) { msr_t msr, perf_ctl; diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index 7d0ed73b4b..1898903853 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -145,3 +145,23 @@ int cpu_configure_thermal_target(struct udevice *dev) return 0; } + +void cpu_set_perf_control(uint clk_ratio) +{ + msr_t perf_ctl; + + perf_ctl.lo = (clk_ratio & 0xff) << 8; + perf_ctl.hi = 0; + msr_write(MSR_IA32_PERF_CTL, perf_ctl); + debug("CPU: frequency set to %d MHz\n", clk_ratio * INTEL_BCLK_MHZ); +} + +bool cpu_config_tdp_levels(void) +{ + msr_t platform_info; + + /* Bits 34:33 indicate how many levels supported */ + platform_info = msr_read(MSR_PLATFORM_INFO); + + return ((platform_info.hi >> 1) & 3) != 0; +} diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 3177ba3297..56ab6bf4ac 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -140,19 +140,16 @@ static const u8 power_limit_time_msr_to_sec[] = { [0x11] = 128, }; -int cpu_config_tdp_levels(void) +bool cpu_ivybridge_config_tdp_levels(void) { struct cpuid_result result; - msr_t platform_info; /* Minimum CPU revision */ result = cpuid(1); if (result.eax < IVB_CONFIG_TDP_MIN_CPUID) - return 0; + return false; - /* Bits 34:33 indicate how many levels supported */ - platform_info = msr_read(MSR_PLATFORM_INFO); - return (platform_info.hi >> 1) & 3; + return cpu_config_tdp_levels(); } /* @@ -213,7 +210,7 @@ void set_power_limits(u8 power_limit_1_time) msr_write(MSR_PKG_POWER_LIMIT, limit); /* Use nominal TDP values for CPUs with configurable TDP */ - if (cpu_config_tdp_levels()) { + if (cpu_ivybridge_config_tdp_levels()) { msr = msr_read(MSR_CONFIG_TDP_NOMINAL); limit.hi = 0; limit.lo = msr.lo & 0xff; @@ -329,24 +326,20 @@ static void configure_dca_cap(void) static void set_max_ratio(void) { - msr_t msr, perf_ctl; - - perf_ctl.hi = 0; + msr_t msr; + uint ratio; /* Check for configurable TDP option */ - if (cpu_config_tdp_levels()) { + if (cpu_ivybridge_config_tdp_levels()) { /* Set to nominal TDP ratio */ msr = msr_read(MSR_CONFIG_TDP_NOMINAL); - perf_ctl.lo = (msr.lo & 0xff) << 8; + ratio = msr.lo & 0xff; } else { /* Platform Info bits 15:8 give max ratio */ msr = msr_read(MSR_PLATFORM_INFO); - perf_ctl.lo = msr.lo & 0xff00; + ratio = (msr.lo & 0xff00) >> 8; } - msr_write(MSR_IA32_PERF_CTL, perf_ctl); - - debug("model_x06ax: frequency set to %d\n", - ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ); + cpu_set_perf_control(ratio); } static void set_energy_perf_bias(u8 policy) diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c index a809b823b3..0f427afcb8 100644 --- a/arch/x86/cpu/ivybridge/northbridge.c +++ b/arch/x86/cpu/ivybridge/northbridge.c @@ -141,7 +141,7 @@ static void northbridge_init(struct udevice *dev, int rev) * CPUs with configurable TDP also need power limits set * in MCHBAR. Use same values from MSR_PKG_POWER_LIMIT. */ - if (cpu_config_tdp_levels()) { + if (cpu_ivybridge_config_tdp_levels()) { msr_t msr = msr_read(MSR_PKG_POWER_LIMIT); writel(msr.lo, MCHBAR_REG(0x59A0)); diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h index 10caaa2422..4839ebc312 100644 --- a/arch/x86/include/asm/arch-ivybridge/model_206ax.h +++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h @@ -58,6 +58,6 @@ /* Configure power limits for turbo mode */ void set_power_limits(u8 power_limit_1_time); -int cpu_config_tdp_levels(void); +bool cpu_ivybridge_config_tdp_levels(void); #endif diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index f42eb32308..c61d74e4a0 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* + * Common code for Intel CPUs + * * Copyright (c) 2016 Google, Inc */ @@ -61,4 +63,20 @@ int cpu_intel_get_info(struct cpu_info *info, int bclk_mz); */ int cpu_configure_thermal_target(struct udevice *dev); +/** + * cpu_set_perf_control() - Set the nominal CPU clock speed + * + * This sets the clock speed as a multiplier of BCLK + * + * @clk_ratio: Ratio to use + */ +void cpu_set_perf_control(uint clk_ratio); + +/** + * cpu_config_tdp_levels() - Check for configurable TDP option + * + * @return true if the CPU has configurable TDP (Thermal-design power) + */ +bool cpu_config_tdp_levels(void); + #endif From f6d00da459694a42c1de1e42b159595e2f5ad56f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:39 -0600 Subject: [PATCH 87/95] x86: Tidy up some duplicate MSR defines Some MSR registers are defined twice in different parts of the file. Move them together and remove the duplicates. Also drop some thermal defines which are not used. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/baytrail/cpu.c | 6 +- arch/x86/cpu/broadwell/cpu_full.c | 6 +- arch/x86/cpu/turbo.c | 10 +-- arch/x86/include/asm/msr-index.h | 106 ++++++++++++------------------ 4 files changed, 54 insertions(+), 74 deletions(-) diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index 2eb917283b..9394eab956 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -68,9 +68,9 @@ static void set_max_freq(void) msr_t msr; /* Enable speed step */ - msr = msr_read(MSR_IA32_MISC_ENABLES); - msr.lo |= (1 << 16); - msr_write(MSR_IA32_MISC_ENABLES, msr); + msr = msr_read(MSR_IA32_MISC_ENABLE); + msr.lo |= MISC_ENABLE_ENHANCED_SPEEDSTEP; + msr_write(MSR_IA32_MISC_ENABLE, msr); /* * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index 169b5b02a6..895edeb4bc 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -470,9 +470,9 @@ static void configure_misc(void) msr_t msr; msr = msr_read(MSR_IA32_MISC_ENABLE); - msr.lo |= (1 << 0); /* Fast String enable */ - msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */ - msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */ + msr.lo |= MISC_ENABLE_FAST_STRING; + msr.lo |= MISC_ENABLE_TM1; + msr.lo |= MISC_ENABLE_ENHANCED_SPEEDSTEP; msr_write(MSR_IA32_MISC_ENABLE, msr); /* Disable thermal interrupts */ diff --git a/arch/x86/cpu/turbo.c b/arch/x86/cpu/turbo.c index a41d511238..be468d2b2c 100644 --- a/arch/x86/cpu/turbo.c +++ b/arch/x86/cpu/turbo.c @@ -60,8 +60,8 @@ int turbo_get_state(void) cpuid_regs = cpuid(CPUID_LEAF_PM); turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE); - msr = msr_read(MSR_IA32_MISC_ENABLES); - turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO); + msr = msr_read(MSR_IA32_MISC_ENABLE); + turbo_en = !(msr.hi & MISC_DISABLE_TURBO); if (!turbo_cap && turbo_en) { /* Unavailable */ @@ -86,9 +86,9 @@ void turbo_enable(void) /* Only possible if turbo is available but hidden */ if (turbo_get_state() == TURBO_DISABLED) { /* Clear Turbo Disable bit in Misc Enables */ - msr = msr_read(MSR_IA32_MISC_ENABLES); - msr.hi &= ~H_MISC_DISABLE_TURBO; - msr_write(MSR_IA32_MISC_ENABLES, msr); + msr = msr_read(MSR_IA32_MISC_ENABLE); + msr.hi &= ~MISC_DISABLE_TURBO; + msr_write(MSR_IA32_MISC_ENABLE, msr); /* Update cached turbo state */ set_global_turbo_state(TURBO_ENABLED); diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 6cb5870809..5bc8b6c22c 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -92,7 +92,38 @@ /* This is burst mode BIT 38 in IA32_MISC_ENABLE MSR at offset 1A0h */ #define BURST_MODE_DISABLE (1 << 6) -#define MSR_IA32_MISC_ENABLES 0x000001a0 +#define MSR_IA32_MISC_ENABLE 0x000001a0 + +/* MISC_ENABLE bits: architectural */ +#define MISC_ENABLE_FAST_STRING BIT_ULL(0) +#define MISC_ENABLE_TCC BIT_ULL(1) +#define MISC_DISABLE_TURBO BIT_ULL(6) +#define MISC_ENABLE_EMON BIT_ULL(7) +#define MISC_ENABLE_BTS_UNAVAIL BIT_ULL(11) +#define MISC_ENABLE_PEBS_UNAVAIL BIT_ULL(12) +#define MISC_ENABLE_ENHANCED_SPEEDSTEP BIT_ULL(16) +#define MISC_ENABLE_MWAIT BIT_ULL(18) +#define MISC_ENABLE_LIMIT_CPUID BIT_ULL(22) +#define MISC_ENABLE_XTPR_DISABLE BIT_ULL(23) +#define MISC_ENABLE_XD_DISABLE BIT_ULL(34) + +/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */ +#define MISC_ENABLE_X87_COMPAT BIT_ULL(2) +#define MISC_ENABLE_TM1 BIT_ULL(3) +#define MISC_ENABLE_SPLIT_LOCK_DISABLE BIT_ULL(4) +#define MISC_ENABLE_L3CACHE_DISABLE BIT_ULL(6) +#define MISC_ENABLE_SUPPRESS_LOCK BIT_ULL(8) +#define MISC_ENABLE_PREFETCH_DISABLE BIT_ULL(9) +#define MISC_ENABLE_FERR BIT_ULL(10) +#define MISC_ENABLE_FERR_MULTIPLEX BIT_ULL(10) +#define MISC_ENABLE_TM2 BIT_ULL(13) +#define MISC_ENABLE_ADJ_PREF_DISABLE BIT_ULL(19) +#define MISC_ENABLE_SPEEDSTEP_LOCK BIT_ULL(20) +#define MISC_ENABLE_L1D_CONTEXT BIT_ULL(24) +#define MISC_ENABLE_DCU_PREF_DISABLE BIT_ULL(37) +#define MISC_ENABLE_TURBO_DISABLE BIT_ULL(38) +#define MISC_ENABLE_IP_PREF_DISABLE BIT_ULL(39) + #define MSR_TEMPERATURE_TARGET 0x1a2 #define MSR_PREFETCH_CTL 0x1a4 #define PREFETCH_L1_DISABLE (1 << 0) @@ -108,6 +139,17 @@ #define ENERGY_POLICY_NORMAL 6 #define ENERGY_POLICY_POWERSAVE 15 +#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 + +#define PACKAGE_THERM_STATUS_PROCHOT BIT(0) +#define PACKAGE_THERM_STATUS_POWER_LIMIT BIT(10) + +#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2 + +#define PACKAGE_THERM_INT_HIGH_ENABLE BIT(0) +#define PACKAGE_THERM_INT_LOW_ENABLE BIT(1) +#define PACKAGE_THERM_INT_PLN_ENABLE BIT(24) + #define MSR_LBR_SELECT 0x000001c8 #define MSR_LBR_TOS 0x000001c9 #define MSR_IA32_PLATFORM_DCA_CAP 0x1f8 @@ -419,68 +461,6 @@ #define MSR_THERM2_CTL_TM_SELECT (1ULL << 16) -#define MSR_IA32_MISC_ENABLE 0x000001a0 -#define H_MISC_DISABLE_TURBO (1 << 6) - -#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 - -#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 -#define ENERGY_PERF_BIAS_PERFORMANCE 0 -#define ENERGY_PERF_BIAS_NORMAL 6 -#define ENERGY_PERF_BIAS_POWERSAVE 15 - -#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 - -#define PACKAGE_THERM_STATUS_PROCHOT (1 << 0) -#define PACKAGE_THERM_STATUS_POWER_LIMIT (1 << 10) - -#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2 - -#define PACKAGE_THERM_INT_HIGH_ENABLE (1 << 0) -#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1) -#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24) - -/* Thermal Thresholds Support */ -#define THERM_INT_THRESHOLD0_ENABLE (1 << 15) -#define THERM_SHIFT_THRESHOLD0 8 -#define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0) -#define THERM_INT_THRESHOLD1_ENABLE (1 << 23) -#define THERM_SHIFT_THRESHOLD1 16 -#define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1) -#define THERM_STATUS_THRESHOLD0 (1 << 6) -#define THERM_LOG_THRESHOLD0 (1 << 7) -#define THERM_STATUS_THRESHOLD1 (1 << 8) -#define THERM_LOG_THRESHOLD1 (1 << 9) - -/* MISC_ENABLE bits: architectural */ -#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) -#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) -#define MSR_IA32_MISC_ENABLE_EMON (1ULL << 7) -#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << 11) -#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << 12) -#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16) -#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) -#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22) -#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << 23) -#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << 34) - -/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */ -#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << 2) -#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << 3) -#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << 4) -#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << 6) -#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << 8) -#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << 9) -#define MSR_IA32_MISC_ENABLE_FERR (1ULL << 10) -#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << 10) -#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << 13) -#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << 19) -#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20) -#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << 24) -#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << 37) -#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) -#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) - #define MSR_IA32_TSC_DEADLINE 0x000006E0 /* P4/Xeon+ specific */ From a27520904f54643c9e55f5672f005a207c911f32 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:40 -0600 Subject: [PATCH 88/95] x86: Add new common CPU functions for turbo/burst mode Add a few more CPU functions that are common on Intel CPUs. Also add attribution for the code source. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: add missing MSR_IA32_MISC_ENABLE write back in cpu_set_eist(); fix 2 typos in cpu_get_burst_mode_state() comments] Signed-off-by: Bin Meng --- arch/x86/cpu/intel_common/cpu.c | 61 +++++++++++++++++++++++++++++++ arch/x86/include/asm/cpu_common.h | 49 +++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index 1898903853..4d093a5391 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -1,12 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 /* + * Copyright (C) 2014 Google Inc. * Copyright (c) 2016 Google, Inc + * Copyright (C) 2015-2018 Intel Corporation. + * Copyright (C) 2018 Siemens AG + * Some code taken from coreboot cpulib.c */ #include #include #include #include +#include #include #include #include @@ -165,3 +170,59 @@ bool cpu_config_tdp_levels(void) return ((platform_info.hi >> 1) & 3) != 0; } + +void cpu_set_p_state_to_turbo_ratio(void) +{ + msr_t msr; + + msr = msr_read(MSR_TURBO_RATIO_LIMIT); + cpu_set_perf_control(msr.lo); +} + +enum burst_mode_t cpu_get_burst_mode_state(void) +{ + enum burst_mode_t state; + int burst_en, burst_cap; + msr_t msr; + uint eax; + + eax = cpuid_eax(0x6); + burst_cap = eax & 0x2; + msr = msr_read(MSR_IA32_MISC_ENABLE); + burst_en = !(msr.hi & BURST_MODE_DISABLE); + + if (!burst_cap && burst_en) + state = BURST_MODE_UNAVAILABLE; + else if (burst_cap && !burst_en) + state = BURST_MODE_DISABLED; + else if (burst_cap && burst_en) + state = BURST_MODE_ENABLED; + else + state = BURST_MODE_UNKNOWN; + + return state; +} + +void cpu_set_burst_mode(bool burst_mode) +{ + msr_t msr; + + msr = msr_read(MSR_IA32_MISC_ENABLE); + if (burst_mode) + msr.hi &= ~BURST_MODE_DISABLE; + else + msr.hi |= BURST_MODE_DISABLE; + msr_write(MSR_IA32_MISC_ENABLE, msr); +} + +void cpu_set_eist(bool eist_status) +{ + msr_t msr; + + msr = msr_read(MSR_IA32_MISC_ENABLE); + if (eist_status) + msr.lo |= MISC_ENABLE_ENHANCED_SPEEDSTEP; + else + msr.lo &= ~MISC_ENABLE_ENHANCED_SPEEDSTEP; + msr_write(MSR_IA32_MISC_ENABLE, msr); +} diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index c61d74e4a0..cdd99a90b7 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -79,4 +79,53 @@ void cpu_set_perf_control(uint clk_ratio); */ bool cpu_config_tdp_levels(void); +/** enum burst_mode_t - Burst-mode states */ +enum burst_mode_t { + BURST_MODE_UNKNOWN, + BURST_MODE_UNAVAILABLE, + BURST_MODE_DISABLED, + BURST_MODE_ENABLED +}; + +/* + * cpu_get_burst_mode_state() - Get the Burst/Turbo Mode State + * + * This reads MSR IA32_MISC_ENABLE 0x1A0 + * Bit 38 - TURBO_MODE_DISABLE Bit to get state ENABLED / DISABLED. + * Also checks cpuid 0x6 to see whether burst mode is supported. + * + * @return current burst mode status + */ +enum burst_mode_t cpu_get_burst_mode_state(void); + +/** + * cpu_set_burst_mode() - Set CPU burst mode + * + * @burst_mode: true to enable burst mode, false to disable + */ +void cpu_set_burst_mode(bool burst_mode); + +/** + * cpu_set_eist() - Enable Enhanced Intel Speed Step Technology + * + * @eist_status: true to enable EIST, false to disable + */ +void cpu_set_eist(bool eist_status); + +/** + * cpu_set_p_state_to_turbo_ratio() - Set turbo ratio + * + * TURBO_RATIO_LIMIT MSR (0x1AD) Bits 31:0 indicates the + * factory configured values for of 1-core, 2-core, 3-core + * and 4-core turbo ratio limits for all processors. + * + * 7:0 - MAX_TURBO_1_CORE + * 15:8 - MAX_TURBO_2_CORES + * 23:16 - MAX_TURBO_3_CORES + * 31:24 - MAX_TURBO_4_CORES + * + * Set PERF_CTL MSR (0x199) P_Req with that value. + */ +void cpu_set_p_state_to_turbo_ratio(void); + #endif From 594d272cfd3dc43f118efb952676715b0382af24 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:41 -0600 Subject: [PATCH 89/95] dm: core: Drop fdtdec_get_pci_addr() This function ise effectively replaced by ofnode_read_pci_addr() which works with flat tree. Delete it to avoid code duplication. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/core/fdtaddr.c | 13 ++++------ include/fdtdec.h | 17 ------------- lib/fdtdec.c | 54 ------------------------------------------ 3 files changed, 5 insertions(+), 79 deletions(-) diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index c9a941116a..575798fae9 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -202,16 +202,13 @@ fdt_addr_t devfdt_get_addr_pci(struct udevice *dev) u32 bar; int ret; - ret = fdtdec_get_pci_addr(gd->fdt_blob, - dev_of_offset(dev), - FDT_PCI_SPACE_MEM32, "reg", - &pci_addr); + ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_MEM32, + "reg", &pci_addr); if (ret) { /* try if there is any i/o-mapped register */ - ret = fdtdec_get_pci_addr(gd->fdt_blob, - dev_of_offset(dev), - FDT_PCI_SPACE_IO, "reg", - &pci_addr); + ret = ofnode_read_pci_addr(dev_ofnode(dev), + FDT_PCI_SPACE_IO, "reg", + &pci_addr); if (ret) return FDT_ADDR_T_NONE; } diff --git a/include/fdtdec.h b/include/fdtdec.h index 635f53083b..f1e58f9732 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -416,23 +416,6 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, const char *prop_name, fdt_size_t *sizep); -/** - * Look at an address property in a node and return the pci address which - * corresponds to the given type in the form of fdt_pci_addr. - * The property must hold one fdt_pci_addr with a lengh. - * - * @param blob FDT blob - * @param node node to examine - * @param type pci address type (FDT_PCI_SPACE_xxx) - * @param prop_name name of property to find - * @param addr returns pci address in the form of fdt_pci_addr - * @return 0 if ok, -ENOENT if the property did not exist, -EINVAL if the - * format of the property was invalid, -ENXIO if the requested - * address type was not found - */ -int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, - const char *prop_name, struct fdt_pci_addr *addr); - /** * Look at the compatible property of a device node that represents a PCI * device and extract pci vendor id and device id from it. diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 74430c8b2f..17736ce665 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -186,60 +186,6 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name) } #if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI) -int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, - const char *prop_name, struct fdt_pci_addr *addr) -{ - const u32 *cell; - int len; - int ret = -ENOENT; - - debug("%s: %s: ", __func__, prop_name); - - /* - * If we follow the pci bus bindings strictly, we should check - * the value of the node's parent node's #address-cells and - * #size-cells. They need to be 3 and 2 accordingly. However, - * for simplicity we skip the check here. - */ - cell = fdt_getprop(blob, node, prop_name, &len); - if (!cell) - goto fail; - - if ((len % FDT_PCI_REG_SIZE) == 0) { - int num = len / FDT_PCI_REG_SIZE; - int i; - - for (i = 0; i < num; i++) { - debug("pci address #%d: %08lx %08lx %08lx\n", i, - (ulong)fdt32_to_cpu(cell[0]), - (ulong)fdt32_to_cpu(cell[1]), - (ulong)fdt32_to_cpu(cell[2])); - if ((fdt32_to_cpu(*cell) & type) == type) { - addr->phys_hi = fdt32_to_cpu(cell[0]); - addr->phys_mid = fdt32_to_cpu(cell[1]); - addr->phys_lo = fdt32_to_cpu(cell[2]); - break; - } - - cell += (FDT_PCI_ADDR_CELLS + - FDT_PCI_SIZE_CELLS); - } - - if (i == num) { - ret = -ENXIO; - goto fail; - } - - return 0; - } - - ret = -EINVAL; - -fail: - debug("(not found)\n"); - return ret; -} - int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device) { const char *list, *end; From 75d8f49481a5c260d0cf1024d41f0b29d57e0efe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:42 -0600 Subject: [PATCH 90/95] sandbox: pci: Create a new sandbox_pci_read_bar() function The code in swapcase can be used by other sandbox drivers. Move it into a common place to allow this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: remove inclusion of in pci_sandbox.c] Signed-off-by: Bin Meng --- arch/sandbox/include/asm/test.h | 15 +++++++++++++++ drivers/misc/Makefile | 2 +- drivers/misc/swap_case.c | 18 +++--------------- drivers/pci/pci-emul-uclass.c | 20 ++++++++++++++++++++ 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 1b21af6bed..cd2b9e3155 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -198,4 +198,19 @@ int sandbox_get_pch_spi_protect(struct udevice *dev); */ int sandbox_get_pci_ep_irq_count(struct udevice *dev); +/** + * sandbox_pci_read_bar() - Read the BAR value for a read_config operation + * + * This is used in PCI emulators to read a base address reset. This has special + * rules because when the register is set to 0xffffffff it can be used to + * discover the type and size of the BAR. + * + * @barval: Current value of the BAR + * @type: Type of BAR (PCI_BASE_ADDRESS_SPACE_IO or + * PCI_BASE_ADDRESS_MEM_TYPE_32) + * @size: Size of BAR in bytes + * @return BAR value to return from emulator + */ +uint sandbox_pci_read_bar(u32 barval, int type, uint size); + #endif diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 509c588582..0001d105ba 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_TPL_)CROS_EC_LPC) += cros_ec_lpc.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o +obj-$(CONFIG_SANDBOX) += swap_case.o endif ifdef CONFIG_DM_I2C @@ -52,7 +53,6 @@ obj-$(CONFIG_PCA9551_LED) += pca9551_led.o obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o -obj-$(CONFIG_SANDBOX) += swap_case.o obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c index 75fe641670..11189d16c8 100644 --- a/drivers/misc/swap_case.c +++ b/drivers/misc/swap_case.c @@ -139,25 +139,13 @@ static int sandbox_swap_case_read_config(struct udevice *emul, uint offset, case PCI_BASE_ADDRESS_4: case PCI_BASE_ADDRESS_5: { int barnum; - u32 *bar, result; + u32 *bar; barnum = pci_offset_to_barnum(offset); bar = &plat->bar[barnum]; - result = *bar; - if (*bar == 0xffffffff) { - if (barinfo[barnum].type) { - result = (~(barinfo[barnum].size - 1) & - PCI_BASE_ADDRESS_IO_MASK) | - PCI_BASE_ADDRESS_SPACE_IO; - } else { - result = (~(barinfo[barnum].size - 1) & - PCI_BASE_ADDRESS_MEM_MASK) | - PCI_BASE_ADDRESS_MEM_TYPE_32; - } - } - debug("r bar %d=%x\n", barnum, result); - *valuep = result; + *valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type, + barinfo[barnum].size); break; } case PCI_CAPABILITY_LIST: diff --git a/drivers/pci/pci-emul-uclass.c b/drivers/pci/pci-emul-uclass.c index fd87b3ea4e..0dcf937d9a 100644 --- a/drivers/pci/pci-emul-uclass.c +++ b/drivers/pci/pci-emul-uclass.c @@ -42,6 +42,26 @@ int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn, return *emulp ? 0 : -ENODEV; } +uint sandbox_pci_read_bar(u32 barval, int type, uint size) +{ + u32 result; + + result = barval; + if (result == 0xffffffff) { + if (type == PCI_BASE_ADDRESS_SPACE_IO) { + result = (~(size - 1) & + PCI_BASE_ADDRESS_IO_MASK) | + PCI_BASE_ADDRESS_SPACE_IO; + } else { + result = (~(size - 1) & + PCI_BASE_ADDRESS_MEM_MASK) | + PCI_BASE_ADDRESS_MEM_TYPE_32; + } + } + + return result; +} + static int sandbox_pci_emul_post_probe(struct udevice *dev) { struct sandbox_pci_emul_priv *priv = dev->uclass->priv; From 12e927b0a842408467fe7dbe627ca350d2300348 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:43 -0600 Subject: [PATCH 91/95] x86: Allow the PCH and LPC uclasses to work with of-platdata At present these uclasses assumes that they are used with a device tree. Update them to support of-platdata as well. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/lpc-uclass.c | 2 ++ drivers/pch/pch-uclass.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/x86/lib/lpc-uclass.c b/arch/x86/lib/lpc-uclass.c index 505d7a943d..1302a6e34a 100644 --- a/arch/x86/lib/lpc-uclass.c +++ b/arch/x86/lib/lpc-uclass.c @@ -10,5 +10,7 @@ UCLASS_DRIVER(lpc) = { .id = UCLASS_LPC, .name = "lpc", +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .post_bind = dm_scan_fdt_dev, +#endif }; diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c index caf8b72803..ad4906aa58 100644 --- a/drivers/pch/pch-uclass.c +++ b/drivers/pch/pch-uclass.c @@ -64,5 +64,7 @@ int pch_ioctl(struct udevice *dev, ulong req, void *data, int size) UCLASS_DRIVER(pch) = { .id = UCLASS_PCH, .name = "pch", +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .post_bind = dm_scan_fdt_dev, +#endif }; From 6ccb2f890bb5bfdd6aed4a99294fd77508436c40 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:45 -0600 Subject: [PATCH 92/95] x86: Refactor mtrr_commit() to allow for shared code Move the code that actually sets up the MTRR into another function so it can be used elsewhere in the file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/mtrr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 0939736164..6218d149e3 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -50,11 +50,20 @@ void mtrr_close(struct mtrr_state *state, bool do_caches) enable_caches(); } +static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size) +{ + u64 mask; + + wrmsrl(MTRR_PHYS_BASE_MSR(reg), start | type); + mask = ~(size - 1); + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; + wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask | MTRR_PHYS_MASK_VALID); +} + int mtrr_commit(bool do_caches) { struct mtrr_request *req = gd->arch.mtrr_req; struct mtrr_state state; - uint64_t mask; int i; debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr, @@ -65,12 +74,8 @@ int mtrr_commit(bool do_caches) debug("open\n"); mtrr_open(&state, do_caches); debug("open done\n"); - for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { - mask = ~(req->size - 1); - mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; - wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type); - wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID); - } + for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) + set_var_mtrr(i, req->type, req->start, req->size); /* Clear the ones that are unused */ debug("clear\n"); From add3f4c9186fbd94b6e89c1d277b544a7a6ad404 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:46 -0600 Subject: [PATCH 93/95] x86: Add a function to set variable MTRRs Normally U-Boot handles MTRRs through an add/commit process which overwrites all MTRRs. But in very early boot it is not desirable to clear the existing MTRRs since they may be in use and it can cause a hang. Add a new mtrr_set_next_var() function which sets up the next available MTRR to the required region. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: pass 'type' to set_var_mtrr() in mtrr_set_next_var()] Signed-off-by: Bin Meng --- arch/x86/cpu/mtrr.c | 38 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 12 ++++++++++++ 2 files changed, 50 insertions(+) diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 6218d149e3..a00db422e7 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -112,3 +112,41 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size) return 0; } + +static int get_var_mtrr_count(void) +{ + return msr_read(MSR_MTRR_CAP_MSR).lo & MSR_MTRR_CAP_VCNT; +} + +static int get_free_var_mtrr(void) +{ + struct msr_t maskm; + int vcnt; + int i; + + vcnt = get_var_mtrr_count(); + + /* Identify the first var mtrr which is not valid */ + for (i = 0; i < vcnt; i++) { + maskm = msr_read(MTRR_PHYS_MASK_MSR(i)); + if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0) + return i; + } + + /* No free var mtrr */ + return -ENOSPC; +} + +int mtrr_set_next_var(uint type, uint64_t start, uint64_t size) +{ + int mtrr; + + mtrr = get_free_var_mtrr(); + if (mtrr < 0) + return mtrr; + + set_var_mtrr(mtrr, type, start, size); + debug("MTRR %x: start=%x, size=%x\n", mtrr, (uint)start, (uint)size); + + return 0; +} diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 6f29e75ce6..672617256e 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -117,6 +117,18 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size); */ int mtrr_commit(bool do_caches); +/** + * mtrr_set_next_var() - set up a variable MTRR + * + * This finds the first free variable MTRR and sets to the given area + * + * @type: Requested type (MTRR_TYPE_) + * @start: Start address + * @size: Size + * @return 0 on success, -ENOSPC if there are no more MTRRs + */ +int mtrr_set_next_var(uint type, uint64_t base, uint64_t size); + #endif #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) From b377ebbd5b8fc371b0b27dd3551f2cc3718757dc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:48 -0600 Subject: [PATCH 94/95] x86: cpu: Don't include the cpu driver in TPL We don't need this driver very early in boot and it adds code size. Drop it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 3f1f62da2b..6296b55ff8 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -26,7 +26,10 @@ endif extra-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += resetvec.o start16.o -obj-y += cpu.o cpu_x86.o +obj-y += cpu.o +ifndef CONFIG_TPL_BUILD +obj-y += cpu_x86.o +endif ifndef CONFIG_$(SPL_)X86_64 AFLAGS_REMOVE_call32.o := -mregparm=3 \ From cc2d27dcdc3e1c76d09d54015e3992380bd7e0fa Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Sep 2019 08:56:49 -0600 Subject: [PATCH 95/95] x86: Use mtrr_commit() with FSP2 With FSP2 we use MTRRs in U-Boot proper even though the 32-bit init happens in TPL. Enable this, using a variable to try to make the conditions more palatable. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/init_helpers.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 4774a9bdb7..3e3a11ac2f 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -12,15 +12,23 @@ DECLARE_GLOBAL_DATA_PTR; int init_cache_f_r(void) { -#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) && \ - !defined(CONFIG_SYS_SLIMBOOTLOADER) + bool do_mtrr = CONFIG_IS_ENABLED(X86_32BIT_INIT) || + IS_ENABLED(CONFIG_FSP_VERSION2); int ret; - ret = mtrr_commit(false); - /* If MTRR MSR is not implemented by the processor, just ignore it */ - if (ret && ret != -ENOSYS) - return ret; -#endif + do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) && + !IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER); + + if (do_mtrr) { + ret = mtrr_commit(false); + /* + * If MTRR MSR is not implemented by the processor, just ignore + * it + */ + if (ret && ret != -ENOSYS) + return ret; + } + /* Initialise the CPU cache(s) */ return init_cache(); }