diff --git a/Makefile b/Makefile
index 54da5cd51cea5cb4aa46bd94b928de082e4926a7..3593039303180d6b1371c9e86966f5615732a6e3 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
@@ -1213,7 +1217,9 @@ 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) \
-                build -u -d u-boot.dtb -O . -m \
+                --toolpath $(objtree)/tools \
+		$(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/arch/arm/Kconfig b/arch/arm/Kconfig
index 3b0e315061aafcaee60309bcf00443c7d5006596..7086db368fb6e7a6e553950b853fe5bba13080b1 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/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
index fdb0c926fb2ced72fbc7511707573ed336de5741..b051025bb0a568d9c36883942b5cbf89802d6c5d 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/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index ed8056e87186777eaac8fbc91831bb62838aabc2..4c87cbc00f743e4c13e1b6f792054796442874e0 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 52ab89142578fbb819a912398516ea98d1a5ec6d..8343000c8faae5055419af0f94d64e38546612c1 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 1441c8069207bb066ef1d3910ea1e0075ce92e7b..d5e437f0d2e2b4e67df9f6f9282c29a5b75d1ce8 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 1d914648e314fbfde805c3947c2a1d927b3fb486..45de153aa5ab84b4faa948cc560219ccee8c9872 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
@@ -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/arch/arm/mach-uniphier/pinctrl-glue.c b/arch/arm/mach-uniphier/pinctrl-glue.c
index c4d3b17c39d8457817ea514acc6552bbca1f41c3..b45f72f59a77862b8256f4bd19d6d2db77694d5a 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/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index fdfb209f77dbd16b30c05d9b20505983e96430e3..2046cb53c4ae6cc4008d29e5e23371996d2a0e40 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/cpu/spl.c b/arch/sandbox/cpu/spl.c
index 4f415c71d63227272db33cb7a761409f9814d8f1..44c68a39bc628e75115b6e693c9d5c30061a79a3 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/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 82828f0c1d45f5dcbb7fa7e28c6656e468189a3b..cfc542c8066f84f0d4cd15ac69b30687f60162be 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/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index c6d5650c20b7fe45b67cdfc4dd37e9ae8846462d..f09bc70b0da71dc2b73f0989b367d7ecbb791356 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 27b0baab2781717ddbaf2a9128666275f4bb6ef0..25cac056bbdf2952fa383d79bf72ed88f465bb42 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -447,29 +447,39 @@
 		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";
 			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;
-			};
+			/* 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>;
-			emul@1f,0 {
-				compatible = "sandbox,swap-case";
-			};
+			/* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */
+			reg = <0x0100f810 0 0 0 0>;
+			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 +509,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";
 		};
 	};
 
@@ -713,11 +728,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/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 2a350a826c4bc240a61479273f0cb1fc43c4e90a..4a35c419723edbeb9aff2e4a926c2fe636960a8a 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
 
 /*
@@ -110,13 +120,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 +206,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 <iotrace.h>
 #include <asm/types.h>
 
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 2d773d3fa6b53c9f0477161b4b352a8c8c4125ca..ad3e94beb9a77e79e6167cf2852b2eb7614ecf52 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.
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index cbf209693daeacdb5c84dcc625c134df043c1dae..cd2b9e3155d73adb1a38c3191cb00477f22c2f7c 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
 
@@ -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/arch/sandbox/lib/pci_io.c b/arch/sandbox/lib/pci_io.c
index 01822c606956cb04e74fd425afca688f2c331cb4..f22e47c7f6da1f65dabd13c9aec4d18d3b0d7407 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);
 }
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 218e817cf3f8126415693eeb7eea40ff77698cfd..47bf28c434f173a1a9dc9f7ea3875e8b8e9b959f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -364,6 +364,37 @@ 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
+	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 +460,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/Makefile b/arch/x86/cpu/Makefile
index 3f1f62da2b1d23ff7b9096708bd5ae87ee5ab885..6296b55ff8ad2d26928c4c4b2b4ccf47e6f36b59 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 \
diff --git a/arch/x86/cpu/baytrail/acpi.c b/arch/x86/cpu/baytrail/acpi.c
index 445e4ba2d7f6c2369a60f6b6587849149b6bdf49..f44228e693980080868f3646e2a6ca454934b60a 100644
--- a/arch/x86/cpu/baytrail/acpi.c
+++ b/arch/x86/cpu/baytrail/acpi.c
@@ -4,10 +4,10 @@
  */
 
 #include <common.h>
+#include <acpi_s3.h>
 #include <cpu.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
-#include <asm/acpi_s3.h>
 #include <asm/acpi_table.h>
 #include <asm/io.h>
 #include <asm/tables.h>
@@ -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/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 2eb917283bc00b932de1850541170a9c2d86bc7b..9394eab956ba1fca12e1f08ed9aa13b8396c4838 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/baytrail/fsp_configs.c b/arch/x86/cpu/baytrail/fsp_configs.c
index cefd26299a438ea1dacfdc5b9ff304e5d96d8127..1d1948c91a8d1808b9e1d9cfabbdcd5e3face682 100644
--- a/arch/x86/cpu/baytrail/fsp_configs.c
+++ b/arch/x86/cpu/baytrail/fsp_configs.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <fdtdec.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -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 7fe6fa7995a82c71ca445da9bb15d4a05219d5a5..60101d742d15e34a29d02a76d9a9b1af6360b63d 100644
--- a/arch/x86/cpu/braswell/fsp_configs.c
+++ b/arch/x86/cpu/braswell/fsp_configs.c
@@ -5,7 +5,7 @@
 
 #include <common.h>
 #include <fdtdec.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -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/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index bb7c3614081ecece400de3752f22f6d138c136b2..55a7439f1c103b0dacda17b27437c65c5ffd62cf 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;
@@ -57,17 +54,22 @@ 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);
+	      ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ);
 }
 
 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)
@@ -98,11 +100,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/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c
index c1db18454987a7433815ae37a528c165e0df7e32..895edeb4bc423edd8cf17759240365d8d4c7938c 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
@@ -322,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;
@@ -339,7 +337,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 */
@@ -350,10 +348,10 @@ 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);
+	      ((perf_ctl.lo >> 8) & 0xff) * INTEL_BCLK_MHZ);
 }
 
 int broadwell_init(struct udevice *dev)
@@ -472,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 */
@@ -488,24 +486,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;
@@ -555,7 +535,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();
@@ -645,14 +625,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, INTEL_BCLK_MHZ);
 }
 
 static int broadwell_get_count(struct udevice *dev)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 290ee084e5e9ac7726c1115e3ffd84390bd95aeb..9ee4b0294aef6f3cc5ebf869e7ccfd17e141603d 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -19,13 +19,13 @@
  */
 
 #include <common.h>
+#include <acpi_s3.h>
 #include <command.h>
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <syscon.h>
 #include <asm/acpi.h>
-#include <asm/acpi_s3.h>
 #include <asm/acpi_table.h>
 #include <asm/control_regs.h>
 #include <asm/coreboot_tables.h>
diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c
index d0ac17808c3e3d9f55407446821eb0c4ad378426..4d093a539129ed35cccf69f9111f66f515565593 100644
--- a/arch/x86/cpu/intel_common/cpu.c
+++ b/arch/x86/cpu/intel_common/cpu.c
@@ -1,11 +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 <common.h>
+#include <cpu.h>
 #include <dm.h>
 #include <errno.h>
+#include <asm/cpu.h>
 #include <asm/cpu_common.h>
 #include <asm/intel_regs.h>
 #include <asm/lapic.h>
@@ -110,3 +116,113 @@ 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(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;
+
+	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;
+}
+
+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;
+}
+
+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/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c
index a6233c75ce2cc2c0b1a18d05e70de9ec73cbe71e..b7bb524162f6f0e48cf2a38005cdd8c5d56a41c4 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 <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <handoff.h>
 #include <asm/cpu_common.h>
 #include <asm/intel_regs.h>
 #include <asm/lapic.h>
@@ -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/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index c8b16e32c0342ed02d5f110b165d41d74a69ccca..6db9da81b71b0e7a58dfa7e7c517b14d9fceec99 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/ivybridge/fsp_configs.c b/arch/x86/cpu/ivybridge/fsp_configs.c
index 2fd06b3bed76dacce498cc2a6585af8cbd4d6b66..0e6453c84778f9227219d6bfda62dc4f36d56f1b 100644
--- a/arch/x86/cpu/ivybridge/fsp_configs.c
+++ b/arch/x86/cpu/ivybridge/fsp_configs.c
@@ -5,11 +5,11 @@
 
 #include <common.h>
 #include <fdtdec.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 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/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index 6edc3e233c29f4cceaadfa7a6f80c7ee8a575f31..56ab6bf4acf5c7db82c94cb03d69aacd4aabd509 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -12,6 +12,7 @@
 #include <fdtdec.h>
 #include <malloc.h>
 #include <asm/cpu.h>
+#include <asm/cpu_common.h>
 #include <asm/cpu_x86.h>
 #include <asm/msr.h>
 #include <asm/msr-index.h>
@@ -139,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();
 }
 
 /*
@@ -212,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;
@@ -282,26 +280,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;
@@ -348,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) * SANDYBRIDGE_BCLK);
+	cpu_set_perf_control(ratio);
 }
 
 static void set_energy_perf_bias(u8 policy)
@@ -413,10 +387,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 */
@@ -436,12 +411,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, INTEL_BCLK_MHZ);
 
 	return 0;
 }
diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c
index a809b823b3bcf8997756527c09834d32b5c4be2b..0f427afcb826b8be6e04c10929899df7ccb1b98d 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/cpu/mtrr.c b/arch/x86/cpu/mtrr.c
index 0939736164d496ea8f2ad0ffa107837302db230d..a00db422e7a91ace8f28032ebdd0c845bc453158 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");
@@ -107,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/cpu/pci.c b/arch/x86/cpu/pci.c
index c6218250e161f12e65d190daa3f5b9f3344b6e3e..e1aae158ce577318a559a5332a8b4fe9de0ad0d3 100644
--- a/arch/x86/cpu/pci.c
+++ b/arch/x86/cpu/pci.c
@@ -16,8 +16,8 @@
 #include <asm/io.h>
 #include <asm/pci.h>
 
-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) {
@@ -35,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) {
@@ -54,6 +54,21 @@ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset,
 	return 0;
 }
 
+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(bdf, offset, &value, size);
+	if (ret)
+		return ret;
+	value &= ~clr;
+	value |= set;
+
+	return pci_x86_write_config(bdf, offset, value, size);
+}
+
 void pci_assign_irqs(int bus, int device, u8 irq[4])
 {
 	pci_dev_t bdf;
diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c
index c4d117783cbf3ada7f8743d503937dc838662ec9..381edd0761587b21747b33ee874f92c0f9f02f88 100644
--- a/arch/x86/cpu/queensbay/fsp_configs.c
+++ b/arch/x86/cpu/queensbay/fsp_configs.c
@@ -5,9 +5,9 @@
  */
 
 #include <common.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
-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/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 76556fc7f79425964f913ddaa678092e6d6fd669..66737e655bbe26df3e4ce69a3fbcf24fd911103c 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -12,7 +12,7 @@
 #include <asm/post.h>
 #include <asm/arch/device.h>
 #include <asm/arch/tnc.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 #include <asm/processor.h>
 
 static int __maybe_unused disable_igd(void)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 3c9bdf2a9d6f026356495f2e5ed03626dc48e157..01524635e9c82d9a498653605dc36d2107ea8d90 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, <graeme.russ@gmail.com>
  *
@@ -90,7 +102,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 +142,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/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
index 4d4e5d0758d44b26720edc16afd1b0f981654499..a73b4d7c4597f7a5df030aa46d0e41b66fa08cc5 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 <sjg@chromium.org>
  */
diff --git a/arch/x86/cpu/start_from_tpl.S b/arch/x86/cpu/start_from_tpl.S
index 44b5363a6852db19a1cb191da54eacf855e366d6..9a4974a5f1b7110bb9296c03f805506406526003 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 <sjg@chromium.org>
diff --git a/arch/x86/cpu/turbo.c b/arch/x86/cpu/turbo.c
index a41d511238dffb8e6d710034fbd59dfac7980bd3..be468d2b2cac5f5b28ce83effb6eacce0e0a46a1 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/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds
index f20c0b810d3cd4750ea31de2d7b5de4014096fe1..c1e9bfbf66f726d7e5a6734c379e9374b5902e73 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 = .;
 
diff --git a/arch/x86/cpu/wakeup.S b/arch/x86/cpu/wakeup.S
index 663b02f27d852975d843dfcc13276cb7dece368c..244ca1276af70834879f9d29e21a6df3dcf3c386 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 <asm/acpi_s3.h>
+#include <acpi_s3.h>
 #include <asm/processor.h>
 #include <asm/processor-flags.h>
 
diff --git a/arch/x86/include/asm/arch-broadwell/cpu.h b/arch/x86/include/asm/arch-broadwell/cpu.h
index ca22a7999680519699df350c03f734e60b8362b9..3bc3bd6609e2a49301f5fd03a2e35aa81f9511fa 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 23153a040fa960e74a8c2f2ab6ae23c87b6e5416..ecdf6d16f94279c6896370fd1be232510a728b94 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 850d96bdd9aa1b5a0f572a81dc7d86f8044bfdfb..4839ebc3124413805f6b0076c11ab00a1db04fd1 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
@@ -61,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 4c91a5daced87871449ad234c1ce1a88cc6b39e5..cdd99a90b768d7801c8ab39e2680ea69dbc42adc 100644
--- a/arch/x86/include/asm/cpu_common.h
+++ b/arch/x86/include/asm/cpu_common.h
@@ -1,12 +1,19 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
+ * Common code for Intel CPUs
+ *
  * Copyright (c) 2016 Google, Inc
  */
 
 #ifndef __ASM_CPU_COMMON_H
 #define __ASM_CPU_COMMON_H
 
-#define IA32_PERF_CTL			0x199
+/* Standard Intel bus clock is fixed at 100MHz */
+enum {
+	INTEL_BCLK_MHZ		= 100
+};
+
+struct cpu_info;
 
 /**
  * cpu_common_init() - Set up common CPU init
@@ -31,4 +38,94 @@ 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/** 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
diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h
index 3bb79c4b67a45c89c26e5ce59cb509c3ef6ee1f4..d248520e972695c82f2360746071b63d2abc159d 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_infoheader.h b/arch/x86/include/asm/fsp/fsp_infoheader.h
index 86f78014b7b623c248b0889b38139bc42cedd5fb..e72c052ed1ecf4e240c9f7c45183dfc45d55f380 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
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h
index 7b92392a2772060eaea651aca27bdda4895612f3..4ac27d26f5537970968a566c088cda61f90d862b 100644
--- a/arch/x86/include/asm/fsp/fsp_support.h
+++ b/arch/x86/include/asm/fsp/fsp_support.h
@@ -7,182 +7,157 @@
 #ifndef __FSP_SUPPORT_H__
 #define __FSP_SUPPORT_H__
 
-#include "fsp_types.h"
-#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 "fsp_azalia.h"
-#include <asm/arch/fsp/fsp_vpd.h>
-#include <asm/arch/fsp/fsp_configs.h>
+#include <asm/fsp/fsp_bootmode.h>
+#include <asm/fsp/fsp_fv.h>
+#include <asm/fsp/fsp_hob.h>
+#include <asm/fsp/fsp_infoheader.h>
+#include <asm/fsp/fsp_types.h>
+#include <asm/fsp_arch.h>
+#include <asm/fsp/fsp_azalia.h>
 
 #define FSP_LOWMEM_BASE		0x100000UL
 #define FSP_HIGHMEM_BASE	0x100000000ULL
 #define UPD_TERMINATOR		0x55AA
 
-
-/**
- * FSP Continuation assembly helper routine
- *
- * This routine jumps to the C version of FSP continuation function
- */
-void asm_continuation(void);
-
-/**
- * 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.
- *
- * @hob_list:    HOB list pointer
- */
-void fsp_init_done(void *hob_list);
-
-/**
- * FSP Continuation function
- *
- * @status:      Always 0
- * @hob_list:    HOB list pointer
- *
- * @retval:      Never returns
- */
-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 *find_fsp_header(void);
-
 /**
- * FSP initialization wrapper function.
+ * fsp_find_header() - Find FSP header offset in FSP image
  *
- * @stack_top: bootloader stack top address
- * @boot_mode: boot mode defined in fsp_bootmode.h
- * @nvs_buf:   Non-volatile memory buffer pointer
+ * @return the offset of FSP header. If signature is invalid, returns 0.
  */
-void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf);
+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 Bootloader temporary stack buffer and size.
+ * fsp_get_var_nvs_data() - get FSP variable Non-volatile Storage HOB buffer
  *
  * @hob_list:      A HOB list pointer.
- * @len:           A pointer to the bootloader temporary stack length.
+ * @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 bootloader temporary stack HOB.
- * @retval others: Bootloader temporary stackbuffer pointer.
+ * @return NULL:   Failed to find the NVS HOB.
+ * @return others: FSP NVS data buffer pointer.
  */
-void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len);
+void *fsp_get_var_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);
 
 /**
- * This function overrides the default configurations of FSP.
+ * 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);
+
+/**
+ * fsp_scan_for_ram_size() - Scan the HOB list to find the RAM size
  *
- * @config:  A pointer to the FSP configuration data structure
- * @rt_buf:  A pointer to the FSP runtime buffer data structure
+ * This sets gd->ram_size based on what it finds.
  *
- * @return:  None
+ * @return 0 if OK, -ve on error
  */
-void update_fsp_configs(struct fsp_config_data *config,
-			struct fspinit_rtbuf *rt_buf);
+int fsp_scan_for_ram_size(void);
 
 /**
- * fsp_init_phase_pci() - Tell the FSP that we have completed PCI init
+ * fsp_prepare_mrc_cache() - Find the DRAM training data from the MRC cache
  *
- * @return 0 if OK, -EPERM if the FSP gave an error.
+ * @return pointer to data, or NULL if no cache or no data found in the cache
  */
-int fsp_init_phase_pci(void);
+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/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_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/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h
new file mode 100644
index 0000000000000000000000000000000000000000..a44a5504a4f8bf71aad729a5f687b244130e2258
--- /dev/null
+++ b/arch/x86/include/asm/fsp1/fsp_support.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#ifndef __FSP1_SUPPORT_H__
+#define __FSP1_SUPPORT_H__
+
+#include <asm/fsp/fsp_support.h>
+#include "fsp_ffs.h"
+
+/**
+ * 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_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.
+ *
+ * @hob_list:    HOB list pointer
+ */
+void fsp_init_done(void *hob_list);
+
+/**
+ * fsp_continue() - FSP Continuation function
+ *
+ * @status:      Always 0
+ * @hob_list:    HOB list pointer
+ *
+ * @return Never returns
+ */
+void fsp_continue(u32 status, void *hob_list);
+
+/**
+ * fsp_init() - FSP initialization wrapper function
+ *
+ * @stack_top: bootloader stack top address
+ * @boot_mode: boot mode defined in fsp_bootmode.h
+ * @nvs_buf:   Non-volatile memory buffer pointer
+ */
+void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf);
+
+/**
+ * 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.
+ *
+ * @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);
+
+/**
+ * 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
+ */
+void fsp_update_configs(struct fsp_config_data *config,
+			struct fspinit_rtbuf *rt_buf);
+
+#endif
diff --git a/arch/x86/include/asm/fsp_arch.h b/arch/x86/include/asm/fsp_arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b2077b3924ef527bb5eebd1c00651e6960fd885
--- /dev/null
+++ b/arch/x86/include/asm/fsp_arch.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * 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 <asm/fsp1/fsp_api.h>
+#include <asm/fsp1/fsp_ffs.h>
+#include <asm/arch/fsp/fsp_vpd.h>
+#include <asm/arch/fsp/fsp_configs.h>
+
+#endif
diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h
index 4d18d59efedb4ca49bf55d515a4318aef9224c6e..aec49b9b815c6e1a1a683c516e9ceeecd1ae844c 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/include/asm/hob.h b/arch/x86/include/asm/hob.h
index b4239821aaa3401ba7381048fd596b28ea8b0cd9..56e11dbb28f02aab661cfd7a634d9cf3565b263c 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/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 9c1dbe61d5965b21b4f31629e929e4c6aed89481..5bc8b6c22c7eab17ed1c41446bc5e356b8029b6b 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,21 +89,67 @@
 #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_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_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
 #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
 #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
@@ -404,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 */
@@ -600,6 +595,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 2d897f82ef791157210f9142d1dbaddeeedb36a9..672617256e9bdea94ed1a5be0aed755f6fdb77f9 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)
 
@@ -116,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)
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 118ac937d93366a260be320a84b65200de259f50..2a7207357284f68c810fc06c7f0fc0a74716f046 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -17,11 +17,48 @@
 
 #ifndef __ASSEMBLY__
 
-int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset,
-			ulong *valuep, enum pci_size_t size);
+/**
+ * pci_x86_read_config() - Read a configuration value from a device
+ *
+ * This function can be called before PCI is set up in driver model.
+ *
+ * @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(pci_dev_t bdf, uint offset, ulong *valuep,
+			enum pci_size_t size);
 
-int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset,
-			 ulong value, 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.
+ *
+ * @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(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.
+ *
+ * @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(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/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h
index 27432b2897913daadc6c7bfb701b87eaa074a486..1bef4877eb33ce57485a4cfe7c58ba09e95bcba5 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/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index c252192bf41455bf09a7aa04d0a2e10feb155e93..2466ad2ad305cc1bef73ff5e511d74eb6dc9b7d4 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 906be5eab98571d528a7353a63fef84131e36279..ca0ca1066b04856a1d052aac4b03e67aeff5fd31 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -44,6 +44,8 @@ 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/acpi_s3.c b/arch/x86/lib/acpi_s3.c
index 03917188a9bc6ff8df37268663a5d7fde2c6bcd8..197636c4b507eb3fd11eb09fae08a344b7d17a9a 100644
--- a/arch/x86/lib/acpi_s3.c
+++ b/arch/x86/lib/acpi_s3.c
@@ -4,8 +4,8 @@
  */
 
 #include <common.h>
+#include <acpi_s3.h>
 #include <asm/acpi.h>
-#include <asm/acpi_s3.h>
 #include <asm/acpi_table.h>
 #include <asm/post.h>
 #include <linux/linkage.h>
diff --git a/arch/x86/lib/coreboot_table.c b/arch/x86/lib/coreboot_table.c
index 2d08a2db0dba68062e5fc7f5f3b7a4c516e052eb..8685aa30467bf4e419e7074c0ad8b68f0020bb02 100644
--- a/arch/x86/lib/coreboot_table.c
+++ b/arch/x86/lib/coreboot_table.c
@@ -4,8 +4,8 @@
  */
 
 #include <common.h>
+#include <acpi_s3.h>
 #include <vbe.h>
-#include <asm/acpi_s3.h>
 #include <asm/coreboot_tables.h>
 #include <asm/e820.h>
 
diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile
index 870de71bd71a940f6e326e648579167cd868655f..9e348564737b0347d1f46d034542575663f73a0e 100644
--- a/arch/x86/lib/fsp/Makefile
+++ b/arch/x86/lib/fsp/Makefile
@@ -1,9 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-# Copyright (C) 2015 Google, Inc
+# Copyright 2019 Google LLC
 
-obj-y += fsp_car.o
 obj-y += fsp_common.o
 obj-y += fsp_dram.o
-obj-$(CONFIG_VIDEO_FSP) += fsp_graphics.o
 obj-y += fsp_support.o
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
index ed0827c6e921901d440c1733dbef10a40462087e..40ba866d77c0845a0044eecfb881c9d0887b3d30 100644
--- a/arch/x86/lib/fsp/fsp_common.c
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -4,10 +4,10 @@
  */
 
 #include <common.h>
+#include <acpi_s3.h>
 #include <dm.h>
 #include <errno.h>
 #include <rtc.h>
-#include <asm/acpi_s3.h>
 #include <asm/cmos_layout.h>
 #include <asm/early_cmos.h>
 #include <asm/io.h>
@@ -55,11 +55,9 @@ void board_final_cleanup(void)
 		debug("fail, error code %x\n", status);
 	else
 		debug("OK\n");
-
-	return;
 }
 
-static __maybe_unused void *fsp_prepare_mrc_cache(void)
+void *fsp_prepare_mrc_cache(void)
 {
 	struct mrc_data_container *cache;
 	struct mrc_region entry;
@@ -104,62 +102,3 @@ int fsp_save_s3_stack(void)
 	return 0;
 }
 #endif
-
-int arch_fsp_init(void)
-{
-	void *nvs;
-	int stack = CONFIG_FSP_TEMP_RAM_ADDR;
-	int boot_mode = BOOT_FULL_CONFIG;
-#ifdef CONFIG_HAVE_ACPI_RESUME
-	int prev_sleep_state = chipset_prev_sleep_state();
-	gd->arch.prev_sleep_state = prev_sleep_state;
-#endif
-
-	if (!gd->arch.hob_list) {
-#ifdef CONFIG_ENABLE_MRC_CACHE
-		nvs = fsp_prepare_mrc_cache();
-#else
-		nvs = NULL;
-#endif
-
-#ifdef CONFIG_HAVE_ACPI_RESUME
-		if (prev_sleep_state == ACPI_S3) {
-			if (nvs == NULL) {
-				/* If waking from S3 and no cache then */
-				debug("No MRC cache found in S3 resume path\n");
-				post_code(POST_RESUME_FAILURE);
-				/* Clear Sleep Type */
-				chipset_clear_sleep_state();
-				/* Reboot */
-				debug("Rebooting..\n");
-				outb(SYS_RST | RST_CPU, IO_PORT_RESET);
-				/* Should not reach here.. */
-				panic("Reboot System");
-			}
-
-			/*
-			 * DM is not available yet at this point, hence call
-			 * CMOS access library which does not depend on DM.
-			 */
-			stack = cmos_read32(CMOS_FSP_STACK_ADDR);
-			boot_mode = BOOT_ON_S3_RESUME;
-		}
-#endif
-		/*
-		 * The first time we enter here, call fsp_init().
-		 * Note the execution does not return to this function,
-		 * instead it jumps to fsp_continue().
-		 */
-		fsp_init(stack, boot_mode, nvs);
-	} else {
-		/*
-		 * The second time we enter here, adjust the size of malloc()
-		 * pool before relocation. Given gd->malloc_base was adjusted
-		 * after the call to board_init_f_init_reserve() in arch/x86/
-		 * cpu/start.S, we should fix up gd->malloc_limit here.
-		 */
-		gd->malloc_limit += CONFIG_FSP_SYS_MALLOC_F_LEN;
-	}
-
-	return 0;
-}
diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c
index 3a23b70410b44e4fc6443f460c350f4277a0a4f8..2d1023068feb856015aab667dd319b46f3e04004 100644
--- a/arch/x86/lib/fsp/fsp_dram.c
+++ b/arch/x86/lib/fsp/fsp_dram.c
@@ -4,6 +4,7 @@
  */
 
 #include <common.h>
+#include <handoff.h>
 #include <asm/fsp/fsp_support.h>
 #include <asm/e820.h>
 #include <asm/mrccache.h>
@@ -11,7 +12,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int dram_init(void)
+int fsp_scan_for_ram_size(void)
 {
 	phys_size_t ram_size = 0;
 	const struct hob_header *hdr;
@@ -22,9 +23,8 @@ int dram_init(void)
 		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) {
+			    res_desc->type == RES_MEM_RESERVED)
 				ram_size += res_desc->len;
-			}
 		}
 		hdr = get_next_hob(hdr);
 	}
@@ -32,13 +32,8 @@ 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,
-					       &gd->arch.mrc_output_len);
-#endif
-
 	return 0;
-}
+};
 
 int dram_init_banksize(void)
 {
@@ -48,19 +43,6 @@ int dram_init_banksize(void)
 	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.
- * It overrides the default implementation found elsewhere which simply
- * picks the end of ram, wherever that may be. The location of the stack,
- * the relocation address, and how far U-Boot is moved by relocation are
- * set in the global data structure.
- */
-ulong board_get_usable_ram_top(ulong total_size)
-{
-	return fsp_get_usable_lowmem_top(gd->arch.hob_list);
-}
-
 unsigned int install_e820_map(unsigned int max_entries,
 			      struct e820_entry *entries)
 {
@@ -98,7 +80,7 @@ unsigned int install_e820_map(unsigned int max_entries,
 	 * 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 + \
+	entries[num_entries].size = gd->ram_top - gd->start_addr_sp +
 		CONFIG_STACK_SIZE;
 	entries[num_entries].type = E820_RESERVED;
 	num_entries++;
@@ -106,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
diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index 0eaa9b232b16689a353c37640ff03a1664ddc00b..983888fd74301cca2b5b13c068eaf41c5bf9e573 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -5,199 +5,9 @@
  */
 
 #include <common.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 #include <asm/post.h>
 
-struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
-{
-	/*
-	 * This function may be called before the a stack is established,
-	 * so special care must be taken. First, it cannot declare any local
-	 * variable using stack. Only register variable can be used here.
-	 * Secondly, some compiler version will add prolog or epilog code
-	 * for the C function. If so the function call may not work before
-	 * stack is ready.
-	 *
-	 * GCC 4.8.1 has been verified to be working for the following codes.
-	 */
-	volatile register u8 *fsp asm("eax");
-
-	/* Initalize the FSP base */
-	fsp = (u8 *)CONFIG_FSP_ADDR;
-
-	/* Check the FV signature, _FVH */
-	if (((struct fv_header *)fsp)->sign == EFI_FVH_SIGNATURE) {
-		/* Go to the end of the FV header and align the address */
-		fsp += ((struct fv_header *)fsp)->ext_hdr_off;
-		fsp += ((struct fv_ext_header *)fsp)->ext_hdr_size;
-		fsp  = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8);
-	} else {
-		fsp  = 0;
-	}
-
-	/* Check the FFS GUID */
-	if (fsp &&
-	    ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 &&
-	    ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 &&
-	    ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 &&
-	    ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 &&
-	    ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 &&
-	    ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 &&
-	    ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 &&
-	    ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 &&
-	    ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 &&
-	    ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 &&
-	    ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 &&
-	    ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 &&
-	    ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 &&
-	    ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 &&
-	    ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 &&
-	    ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) {
-		/* Add the FFS header size to find the raw section header */
-		fsp += sizeof(struct ffs_file_header);
-	} else {
-		fsp = 0;
-	}
-
-	if (fsp &&
-	    ((struct raw_section *)fsp)->type == EFI_SECTION_RAW) {
-		/* Add the raw section header size to find the FSP header */
-		fsp += sizeof(struct raw_section);
-	} else {
-		fsp = 0;
-	}
-
-	return (struct fsp_header *)fsp;
-}
-
-void fsp_continue(u32 status, void *hob_list)
-{
-	post_code(POST_MRC);
-
-	assert(status == 0);
-
-	/* The boot loader main function entry */
-	fsp_init_done(hob_list);
-}
-
-void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
-{
-	struct fsp_config_data config_data;
-	fsp_init_f init;
-	struct fsp_init_params params;
-	struct fspinit_rtbuf rt_buf;
-	struct fsp_header *fsp_hdr;
-	struct fsp_init_params *params_ptr;
-#ifdef CONFIG_FSP_USE_UPD
-	struct vpd_region *fsp_vpd;
-	struct upd_region *fsp_upd;
-#endif
-
-	fsp_hdr = find_fsp_header();
-	if (fsp_hdr == NULL) {
-		/* No valid FSP info header was found */
-		panic("Invalid FSP header");
-	}
-
-	config_data.common.fsp_hdr = fsp_hdr;
-	config_data.common.stack_top = stack_top;
-	config_data.common.boot_mode = boot_mode;
-
-#ifdef CONFIG_FSP_USE_UPD
-	/* Get VPD region start */
-	fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
-			fsp_hdr->cfg_region_off);
-
-	/* Verify the VPD data region is valid */
-	assert(fsp_vpd->sign == VPD_IMAGE_ID);
-
-	fsp_upd = &config_data.fsp_upd;
-
-	/* Copy default data from Flash */
-	memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
-	       sizeof(struct upd_region));
-
-	/* Verify the UPD data region is valid */
-	assert(fsp_upd->terminator == UPD_TERMINATOR);
-#endif
-
-	memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
-
-	/* Override any configuration if required */
-	update_fsp_configs(&config_data, &rt_buf);
-
-	memset(&params, 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;
-
-	init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init);
-	params_ptr = &params;
-
-	post_code(POST_PRE_MRC);
-
-	/* Load GDT for FSP */
-	setup_fsp_gdt();
-
-	/*
-	 * Use ASM code to ensure the register value in EAX & EDX
-	 * will be passed into fsp_continue
-	 */
-	asm volatile (
-		"pushl	%0;"
-		"call	*%%eax;"
-		".global asm_continuation;"
-		"asm_continuation:;"
-		"movl	4(%%esp), %%eax;"	/* status */
-		"movl	8(%%esp), %%edx;"	/* hob_list */
-		"jmp	fsp_continue;"
-		: : "m"(params_ptr), "a"(init)
-	);
-
-	/*
-	 * Should never get here.
-	 * Control will continue from fsp_continue.
-	 * This line below is to prevent the compiler from optimizing
-	 * structure intialization.
-	 *
-	 * DO NOT REMOVE!
-	 */
-	init(&params);
-}
-
-u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
-{
-	fsp_notify_f notify;
-	struct fsp_notify_params params;
-	struct fsp_notify_params *params_ptr;
-	u32 status;
-
-	if (!fsp_hdr)
-		fsp_hdr = (struct fsp_header *)find_fsp_header();
-
-	if (fsp_hdr == NULL) {
-		/* No valid FSP info header */
-		panic("Invalid FSP header");
-	}
-
-	notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
-	params.phase = phase;
-	params_ptr = &params;
-
-	/*
-	 * Use ASM code to ensure correct parameter is on the stack for
-	 * FspNotify as U-Boot is using different ABI from FSP
-	 */
-	asm volatile (
-		"pushl	%1;"		/* push notify phase */
-		"call	*%%eax;"	/* call FspNotify */
-		"addl	$4, %%esp;"	/* clean up the stack */
-		: "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
-	);
-
-	return status;
-}
-
 u32 fsp_get_usable_lowmem_top(const void *hob_list)
 {
 	const struct hob_header *hdr;
@@ -324,7 +134,7 @@ u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len)
 
 	base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
 			&length, &guid);
-	if ((len != 0) && (base != 0))
+	if (len && base)
 		*len = (u32)length;
 
 	return base;
@@ -338,7 +148,7 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
 
 	base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
 			&length, &guid);
-	if ((len != 0) && (base != 0))
+	if (len && base)
 		*len = (u32)length;
 
 	return base;
@@ -351,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;
diff --git a/arch/x86/lib/fsp1/Makefile b/arch/x86/lib/fsp1/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..870de71bd71a940f6e326e648579167cd868655f
--- /dev/null
+++ b/arch/x86/lib/fsp1/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015 Google, Inc
+
+obj-y += fsp_car.o
+obj-y += fsp_common.o
+obj-y += fsp_dram.o
+obj-$(CONFIG_VIDEO_FSP) += fsp_graphics.o
+obj-y += fsp_support.o
diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp1/fsp_car.S
similarity index 94%
rename from arch/x86/lib/fsp/fsp_car.S
rename to arch/x86/lib/fsp1/fsp_car.S
index 8c54cea3db44fd052ffc7337c489815b2aca4bfb..a64a6534357e44e21f6f3dc6fb2ec7ca16d0a689 100644
--- a/arch/x86/lib/fsp/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_common.c b/arch/x86/lib/fsp1/fsp_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..e8066d8de3975803184985d0415b44393698e4ae
--- /dev/null
+++ b/arch/x86/lib/fsp1/fsp_common.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <acpi_s3.h>
+#include <dm.h>
+#include <errno.h>
+#include <rtc.h>
+#include <asm/cmos_layout.h>
+#include <asm/early_cmos.h>
+#include <asm/io.h>
+#include <asm/mrccache.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/fsp1/fsp_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_fsp_init(void)
+{
+	void *nvs;
+	int stack = CONFIG_FSP_TEMP_RAM_ADDR;
+	int boot_mode = BOOT_FULL_CONFIG;
+#ifdef CONFIG_HAVE_ACPI_RESUME
+	int prev_sleep_state = chipset_prev_sleep_state();
+	gd->arch.prev_sleep_state = prev_sleep_state;
+#endif
+
+	if (!gd->arch.hob_list) {
+		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) {
+			if (nvs == NULL) {
+				/* If waking from S3 and no cache then */
+				debug("No MRC cache found in S3 resume path\n");
+				post_code(POST_RESUME_FAILURE);
+				/* Clear Sleep Type */
+				chipset_clear_sleep_state();
+				/* Reboot */
+				debug("Rebooting..\n");
+				outb(SYS_RST | RST_CPU, IO_PORT_RESET);
+				/* Should not reach here.. */
+				panic("Reboot System");
+			}
+
+			/*
+			 * DM is not available yet at this point, hence call
+			 * CMOS access library which does not depend on DM.
+			 */
+			stack = cmos_read32(CMOS_FSP_STACK_ADDR);
+			boot_mode = BOOT_ON_S3_RESUME;
+		}
+#endif
+		/*
+		 * The first time we enter here, call fsp_init().
+		 * Note the execution does not return to this function,
+		 * instead it jumps to fsp_continue().
+		 */
+		fsp_init(stack, boot_mode, nvs);
+	} else {
+		/*
+		 * The second time we enter here, adjust the size of malloc()
+		 * pool before relocation. Given gd->malloc_base was adjusted
+		 * after the call to board_init_f_init_reserve() in arch/x86/
+		 * cpu/start.S, we should fix up gd->malloc_limit here.
+		 */
+		gd->malloc_limit += CONFIG_FSP_SYS_MALLOC_F_LEN;
+	}
+
+	return 0;
+}
diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a3349b42af23f2aa896d17fab6ff89dcf8b9e08
--- /dev/null
+++ b/arch/x86/lib/fsp1/fsp_dram.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/fsp/fsp_support.h>
+
+int dram_init(void)
+{
+	int ret;
+
+	/* 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,
+					       &gd->arch.mrc_output_len);
+
+	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.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	return fsp_get_usable_lowmem_top(gd->arch.hob_list);
+}
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 91d2d08557262c06509f0370f94a3606ea722ad4..52e71334f952c7e977715de2691128e29fa5a91a 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp1/fsp_graphics.c
@@ -7,7 +7,7 @@
 #include <dm.h>
 #include <vbe.h>
 #include <video.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/x86/lib/fsp1/fsp_support.c b/arch/x86/lib/fsp1/fsp_support.c
new file mode 100644
index 0000000000000000000000000000000000000000..c7a2c73846b4bea4036b68a3bb323b7fc1462d7c
--- /dev/null
+++ b/arch/x86/lib/fsp1/fsp_support.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/fsp1/fsp_support.h>
+#include <asm/post.h>
+
+struct fsp_header *__attribute__((optimize("O0"))) fsp_find_header(void)
+{
+	/*
+	 * This function may be called before the a stack is established,
+	 * so special care must be taken. First, it cannot declare any local
+	 * variable using stack. Only register variable can be used here.
+	 * Secondly, some compiler version will add prolog or epilog code
+	 * for the C function. If so the function call may not work before
+	 * stack is ready.
+	 *
+	 * GCC 4.8.1 has been verified to be working for the following codes.
+	 */
+	volatile register u8 *fsp asm("eax");
+
+	/* Initalize the FSP base */
+	fsp = (u8 *)CONFIG_FSP_ADDR;
+
+	/* Check the FV signature, _FVH */
+	if (((struct fv_header *)fsp)->sign == EFI_FVH_SIGNATURE) {
+		/* Go to the end of the FV header and align the address */
+		fsp += ((struct fv_header *)fsp)->ext_hdr_off;
+		fsp += ((struct fv_ext_header *)fsp)->ext_hdr_size;
+		fsp  = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8);
+	} else {
+		fsp  = 0;
+	}
+
+	/* Check the FFS GUID */
+	if (fsp &&
+	    ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 &&
+	    ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 &&
+	    ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 &&
+	    ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 &&
+	    ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 &&
+	    ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 &&
+	    ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 &&
+	    ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 &&
+	    ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 &&
+	    ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 &&
+	    ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 &&
+	    ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 &&
+	    ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 &&
+	    ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 &&
+	    ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 &&
+	    ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) {
+		/* Add the FFS header size to find the raw section header */
+		fsp += sizeof(struct ffs_file_header);
+	} else {
+		fsp = 0;
+	}
+
+	if (fsp &&
+	    ((struct raw_section *)fsp)->type == EFI_SECTION_RAW) {
+		/* Add the raw section header size to find the FSP header */
+		fsp += sizeof(struct raw_section);
+	} else {
+		fsp = 0;
+	}
+
+	return (struct fsp_header *)fsp;
+}
+
+void fsp_continue(u32 status, void *hob_list)
+{
+	post_code(POST_MRC);
+
+	assert(status == 0);
+
+	/* The boot loader main function entry */
+	fsp_init_done(hob_list);
+}
+
+void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
+{
+	struct fsp_config_data config_data;
+	fsp_init_f init;
+	struct fsp_init_params params;
+	struct fspinit_rtbuf rt_buf;
+	struct fsp_header *fsp_hdr;
+	struct fsp_init_params *params_ptr;
+#ifdef CONFIG_FSP_USE_UPD
+	struct vpd_region *fsp_vpd;
+	struct upd_region *fsp_upd;
+#endif
+
+	fsp_hdr = fsp_find_header();
+	if (fsp_hdr == NULL) {
+		/* No valid FSP info header was found */
+		panic("Invalid FSP header");
+	}
+
+	config_data.common.fsp_hdr = fsp_hdr;
+	config_data.common.stack_top = stack_top;
+	config_data.common.boot_mode = boot_mode;
+
+#ifdef CONFIG_FSP_USE_UPD
+	/* Get VPD region start */
+	fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
+			fsp_hdr->cfg_region_off);
+
+	/* Verify the VPD data region is valid */
+	assert(fsp_vpd->sign == VPD_IMAGE_ID);
+
+	fsp_upd = &config_data.fsp_upd;
+
+	/* Copy default data from Flash */
+	memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
+	       sizeof(struct upd_region));
+
+	/* Verify the UPD data region is valid */
+	assert(fsp_upd->terminator == UPD_TERMINATOR);
+#endif
+
+	memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
+
+	/* Override any configuration if required */
+	fsp_update_configs(&config_data, &rt_buf);
+
+	memset(&params, 0, sizeof(struct fsp_init_params));
+	params.nvs_buf = nvs_buf;
+	params.rt_buf = (struct fspinit_rtbuf *)&rt_buf;
+	params.continuation = (fsp_continuation_f)fsp_asm_continuation;
+
+	init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init);
+	params_ptr = &params;
+
+	post_code(POST_PRE_MRC);
+
+	/* Load GDT for FSP */
+	setup_fsp_gdt();
+
+	/*
+	 * Use ASM code to ensure the register value in EAX & EDX
+	 * will be passed into fsp_continue
+	 */
+	asm volatile (
+		"pushl	%0;"
+		"call	*%%eax;"
+		".global fsp_asm_continuation;"
+		"fsp_asm_continuation:;"
+		"movl	4(%%esp), %%eax;"	/* status */
+		"movl	8(%%esp), %%edx;"	/* hob_list */
+		"jmp	fsp_continue;"
+		: : "m"(params_ptr), "a"(init)
+	);
+
+	/*
+	 * Should never get here.
+	 * Control will continue from fsp_continue.
+	 * This line below is to prevent the compiler from optimizing
+	 * structure intialization.
+	 *
+	 * DO NOT REMOVE!
+	 */
+	init(&params);
+}
+
+u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
+{
+	fsp_notify_f notify;
+	struct fsp_notify_params params;
+	struct fsp_notify_params *params_ptr;
+	u32 status;
+
+	if (!fsp_hdr)
+		fsp_hdr = (struct fsp_header *)fsp_find_header();
+
+	if (fsp_hdr == NULL) {
+		/* No valid FSP info header */
+		panic("Invalid FSP header");
+	}
+
+	notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
+	params.phase = phase;
+	params_ptr = &params;
+
+	/*
+	 * Use ASM code to ensure correct parameter is on the stack for
+	 * FspNotify as U-Boot is using different ABI from FSP
+	 */
+	asm volatile (
+		"pushl	%1;"		/* push notify phase */
+		"call	*%%eax;"	/* call FspNotify */
+		"addl	$4, %%esp;"	/* clean up the stack */
+		: "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
+	);
+
+	return status;
+}
diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c
index dcee29b04cfe409fc889a1ea0ac47f0799788d39..f2c47240ee8ee4062b2d89fc8d8aed75a0fada66 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)
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 4774a9bdb78d03339667948f5fab6ba1e70dce08..3e3a11ac2fa93e4bd2675f2cdc012917407182b7 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();
 }
diff --git a/arch/x86/lib/lpc-uclass.c b/arch/x86/lib/lpc-uclass.c
index 505d7a943d2e1e75aa9e6609d8df229abc1b72ee..1302a6e34a144a9f3441ae92d7ecce9768b00666 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/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 5d5d1a9ca749d9ad4acc1b83f27af4892034631e..2baac91383763391c66daa927ecb21d58744f602 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -11,6 +11,7 @@
 #include <asm/mrccache.h>
 #include <asm/mtrr.h>
 #include <asm/processor.h>
+#include <asm/spl.h>
 #include <asm-generic/sections.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -39,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;
@@ -142,7 +138,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 +164,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)
 {
@@ -183,8 +179,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 492a2d65216db3a8a895aba2110c26bd16f4404d..cfefa78045e37120d9e42f121ee63a8d6bc95c13 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)
 {
@@ -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)
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 ac12f303a3befa4f751c9e25decf4991f950bbcf..8f4c587371d920af5c9d18d28fe745ce4535258c 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 <common.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 /* 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 695af6bb7ecaddfc9aa6a7138689611b53733948..c037d5b14cd71c10ca58079b1463acb08f9794f7 100644
--- a/board/intel/cherryhill/cherryhill.c
+++ b/board/intel/cherryhill/cherryhill.c
@@ -5,7 +5,7 @@
 
 #include <common.h>
 #include <asm/arch/gpio.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 static const struct gpio_family gpio_family[] = {
 	GPIO_FAMILY_CONF("SOUTHEAST_2_hshvfamily_2x3_rcomp_7_0", NA, 0,
diff --git a/cmd/io.c b/cmd/io.c
index 79faf814ff739d689825a76b3492f14d30705cc1..7fee9674a2862731c1e81f993ef88afd8745c04c 100644
--- a/cmd/io.c
+++ b/cmd/io.c
@@ -11,6 +11,13 @@
 #include <command.h>
 #include <asm/io.h>
 
+/* 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;
-
-	if (argc != 2)
+	ulong addr, length, bytes;
+	u8 buf[DISP_LINE_LEN];
+	int size, todo;
+
+	/*
+	 * 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;
-
-	addr = simple_strtoul(argv[1], NULL, 16);
-
-	printf("%04x: ", (u16) addr);
-
-	if (size == 4)
-		printf("%08x\n", inl(addr));
-	else if (size == 2)
-		printf("%04x\n", inw(addr));
-	else
-		printf("%02x\n", inb(addr));
+	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;
+
+		/* Address is specified since argc > 1 */
+		addr = simple_strtoul(argv[1], NULL, 16);
+		addr += base_address;
+
+		/*
+		 * 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);
+	}
+
+	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,
diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c
index efa183854b7415f5435221013f7a8161ce33dea9..b3b663021bc1e2b984c9ffda919a0ecf0670427a 100644
--- a/cmd/x86/fsp.c
+++ b/cmd/x86/fsp.c
@@ -5,13 +5,13 @@
 
 #include <common.h>
 #include <command.h>
-#include <asm/fsp/fsp_support.h>
+#include <asm/fsp1/fsp_support.h>
 
 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;
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index f467eca2be729874b385ac04896272718b87a6d9..ef4fb19e52c995620506f873d66fec8e0dabc75c 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
@@ -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
@@ -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"
@@ -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
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 082fa2bd94d7ce47a235a4841bced1fbd307871d..5fdd6d0d032181cfd6e841ede1c2dd47fd6b9701 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;
@@ -404,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) {
@@ -598,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();
diff --git a/common/xyzModem.c b/common/xyzModem.c
index e85da74a698f373c837987228f2a99b4a318a136..6bf2375671d2825668457472e29c9e81a12fef28 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 e69f81b6e549f84b53fbde0f0a4777c87143b50f..1a1d58d3cc8aee1f334345445f08823e1511b00f 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/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index 7b0e908f715c8d994076752ba8268c470ed8a6b3..043ee32bb441186c8f959a58fe4c8d18108706df 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/ls1043ardb_nand_SECURE_BOOT_defconfig b/configs/ls1043ardb_nand_SECURE_BOOT_defconfig
index 7aa8c54a128b2c4eed02e03c026dfebf3673b00b..c45fc68ac3f7198499e78672e32c97b8ccbd048a 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 22ccf526f69640eaecc6799a7e713a9aea5a1385..a9e58047acc4d428f962a62ae25138ac52bc231c 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 486a2e089b775e73c1ef317d9fc1324d6ea03de7..bdfa13a0a71a7512bfd3473204b4ad2c84422897 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 b3c2970207c8cfda6fc06e4b73d50ff3cfb167f7..01adbf0b192fd48cd134aeb288ab3cfe8c517a75 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 0b3391a2a6b7caa29ae862bb340ff014493e87ee..409b8a38d5e0c0205272a67855ce539c94ee3075 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/configs/slimbootloader_defconfig b/configs/slimbootloader_defconfig
index f9fecff45ea068a03d5fa679431bd75b0135b30f..3cbb83c7a47a3867f8473b50c2d727b5f0baa85a 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
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index 93286084525dad92c6d7248d6ae50a1e704ba25a..eff3b06b5ce274844a95c95dc5ab4452a43dbeaf 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
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index 5c0caebcbf0eaaf2773a8d4ac75bb010ab5d7ecf..54933b56759b414d484ab5dc141f7d86ff26d343 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
 ----------
diff --git a/doc/driver-model/debugging.rst b/doc/driver-model/debugging.rst
new file mode 100644
index 0000000000000000000000000000000000000000..4f4a8d4805f57e4a5b96ac8ed2165f07de28f604
--- /dev/null
+++ b/doc/driver-model/debugging.rst
@@ -0,0 +1,62 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
+
+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 ea32c36335f5502733139311fc0364fe07d42893..6d55774b4c2edf9853e5605067414e70a09c1494 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
diff --git a/doc/driver-model/pci-info.rst b/doc/driver-model/pci-info.rst
index d93ab8b61d5dc0adb5e8de814aa23cd21d08a057..3c1b1adf077eb608e41c41146fff71aeb2ad49f9 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.
@@ -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/block/blk-uclass.c b/drivers/block/blk-uclass.c
index baaf431e5e0c3ce64af9b934fa140af496e0b2b5..e8f58b3f5e471b815c619a0a091fab87d5e7d762 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/drivers/core/device.c b/drivers/core/device.c
index 05dadf98f95950f0b5c29a4ff113dcab7ce3ee74..84f0f0fbf0e87b450f33752706577b51e92c05f7 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/core/fdtaddr.c b/drivers/core/fdtaddr.c
index 6850003a287b8b4490e9baf14b5397150324c30e..575798fae93c3d97a8984c62c60493a4adfb2b07 100644
--- a/drivers/core/fdtaddr.c
+++ b/drivers/core/fdtaddr.c
@@ -190,3 +190,33 @@ 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 = 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 = ofnode_read_pci_addr(dev_ofnode(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/lists.c b/drivers/core/lists.c
index a1f828463ecd615ba1e9175fc68cabd35543615a..4681b3e5dd1a02fd4268a089ea75941e94087be7 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -6,6 +6,8 @@
  * Marek Vasut <marex@denx.de>
  */
 
+#define LOG_CATEGORY LOGC_DM
+
 #include <common.h>
 #include <errno.h>
 #include <dm/device.h>
@@ -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;
 }
diff --git a/drivers/core/read.c b/drivers/core/read.c
index fb3dcd9a7905d5178074de82313f8ce5a3758418..9602e52d1b1d3dcd8afbe8d5ef31c9fffa044936 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/core/uclass.c b/drivers/core/uclass.c
index b33296542f63ddfed35739ea891483b03d5504e6..f217876cd2c0ab70a7e81d38c705b39da1c4d040 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);
 
@@ -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;
 }
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 01cfa2f7884884d0a6c61674da5992f2e7a04555..90fbed455b8da8269f49a3062032e199dab2beb7 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/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c
index bbe214d5eea972c71596794ffba62d2fdb3e1602..74a773c099b9d5871ea078564bc6e9cf53cc6265 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;
 }
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 509c588582d2e0f51ca0ca85b8f7b1e2bc3ac26c..0001d105baee00870d5fe47edce1dd3212424e01 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 6afc6d9466bb92869be8117170ede81b04bceea0..11189d16c83ae87fa5227d3b198368db8e288048 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,
 };
@@ -54,13 +51,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);
@@ -129,7 +119,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) {
@@ -149,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 = offset_to_barnum(offset);
+		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:
@@ -231,7 +209,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);
@@ -286,8 +264,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 +282,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,8 +370,7 @@ static int sandbox_swap_case_unmap_physmem(struct udevice *dev,
 	return 0;
 }
 
-struct dm_pci_emul_ops sandbox_swap_case_emul_ops = {
-	.get_devfn = sandbox_swap_case_get_devfn,
+static struct dm_pci_emul_ops sandbox_swap_case_emul_ops = {
 	.read_config = sandbox_swap_case_read_config,
 	.write_config = sandbox_swap_case_write_config,
 	.read_io = sandbox_swap_case_read_io,
@@ -417,7 +394,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/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index c8f71cd0c1b6e34883aa77d6ba54e7f41500ffcf..6bece7f3073a51fd75c9c996d5d0680dfc3f40cc 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/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index 2fa7d8c3dcde8633e5d275e209477880bf3b71bf..899952d773cdd063122cbb37382f5e8bf82c6231 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;
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 719a2fd23ae29fb83d080a9b59faec0ee426ab9c..c6107522be033eb8c0a0ed3dd94f093e2cf04bf6 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/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c
index caf8b72803cac90d7ed8fa0522ef65d07ecde69f..ad4906aa58b41c55859180d0572866413d53460b 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
 };
diff --git a/drivers/pci/pci-emul-uclass.c b/drivers/pci/pci-emul-uclass.c
index 38227583547341f080fa124818521d2dad08277d..0dcf937d9a67bc28a562e6496d3c5cbb68935416 100644
--- a/drivers/pci/pci-emul-uclass.c
+++ b/drivers/pci/pci-emul-uclass.c
@@ -30,17 +30,38 @@ 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_get_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;
 }
 
+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;
@@ -68,3 +89,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/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index ab3e1310eb546d030139d8ead14094890b7cff35..896cb6b23a1a23516fd5b6664b5bf62dd3654beb 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) {
@@ -982,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;
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 1a3bf708347d2269cff25aa7b4f566335ac6ad15..28667bde8da79d6167296072ea6ed898010dd40f 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);
 
diff --git a/drivers/pci/pci_auto_common.c b/drivers/pci/pci_auto_common.c
index 84908e6154c568a3382381aeda2baeaa3ebef01e..86903166101b6732bae0d19c82c69a0ff50d7fae 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;
 	}
 
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 2cede1211bbed341986d6bd1d999c3b83a052bbd..1d4064e3769281537cbd563f0f903555c5c3e435 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -35,7 +35,7 @@
 #include <linux/screen_info.h>
 
 #ifdef CONFIG_X86
-#include <asm/acpi_s3.h>
+#include <acpi_s3.h>
 DECLARE_GLOBAL_DATA_PTR;
 #endif
 
diff --git a/drivers/pci/pci_x86.c b/drivers/pci/pci_x86.c
index 520ea4649e11c1bcda350f02623bbfee9770f3bb..e76a9c6e44fe50ddc4aff96d8bb52a383a31c3bf 100644
--- a/drivers/pci/pci_x86.c
+++ b/drivers/pci/pci_x86.c
@@ -8,9 +8,21 @@
 #include <pci.h>
 #include <asm/pci.h>
 
+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[] = {
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 6cf2be8f2b892eb0fd7cfea13ddf825b4380724b..754b6e99215822190b1b2eecb7c592302895904b 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);
@@ -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/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 33102fc872f20fd1b1533403ed9c33022fc7df41..2f7bc248871ff8a2e8ce836a9804beb6563b5f11 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);
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index f565ae031095c3d40f95675acafc357320b243f3..5e6293ae69b949aca2b52aabe8e3667bd7f492f7 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 cf01492295f7dccbafaa6a3fd6198e68c37c2cef..fff4a184a02fd47922fe60b02436fe4ab69f3d90 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
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c
index 072f7948efa1be8aa7305b82c58fbc9df5a0e47b..8e2d1eaa7a1312e10cc56711d5f2737cdcb31b5e 100644
--- a/drivers/sysreset/sysreset_x86.c
+++ b/drivers/sysreset/sysreset_x86.c
@@ -6,11 +6,11 @@
  */
 
 #include <common.h>
+#include <acpi_s3.h>
 #include <dm.h>
 #include <efi_loader.h>
 #include <pch.h>
 #include <sysreset.h>
-#include <asm/acpi_s3.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 
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
diff --git a/include/configs/mxs.h b/include/configs/mxs.h
index 6cadd720d2b958cc01821f4934f40b7eb4dbe573..e079f8035b8baf8fc1f822c761dd6f0d26b0614c 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/include/dm/device.h b/include/dm/device.h
index 27a6d7b9fdb0da75049a285bb14fb562fca710c3..d1210429e9230788afe4c59af7d418b2f6d21352 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
  *
diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h
index 57b326cb3362d109bcea76cf0118ddb31b48252e..959d3bc2d69934937b217932867c53ffc60fcbaa 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 803daf7620c8ab623aa2b0e67fc0991849e49e69..d37fcb504d3471d48455fb769008a1321af820ab 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/include/dm/uclass-id.h b/include/dm/uclass-id.h
index d4d96106b3728231c4e1f0abae97c1fac8b697f1..f431f3bf294dcd46e7f9e119f19eea42037d95fc 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 */
 
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index 6977995246da138e394c553807ea65dd704ba01a..6e3f15c2b0804c07f91b03e6f20f77e9b6527596 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/include/ec_commands.h b/include/ec_commands.h
index 392c1f1a43a74168b383941c8e9b56cfa1c6fc86..444ba61e591524e6ae8e021d145a708643ed558e 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 */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 53b369945b432ff0aa90c21f24ff0e3cb6642b52..381da80cdce0dbd7b74a037d23b76d986375f4a8 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -12,6 +12,11 @@
 #include <part_efi.h>
 #include <efi_api.h>
 
+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
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 635f53083b7bb85799ab96ae6c36b685879b5719..f1e58f9732dbf1de5957781b28bc8da97b92cfec 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/include/handoff.h b/include/handoff.h
index aacb0f5ebf2e6e8736fcfabce4d7f39ab5bf27de..75d19b1f6e511174cf48eac30b8d0dd8e6914c3d 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
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 709b49d3936da1cc0858c1d42afd6736cf01e2f0..f9964a7664568615831b839d2f9e850c44b84ff8 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
 
 /**
diff --git a/include/log.h b/include/log.h
index 6d15e955d7e29b9c9fd99e3936032baf7ce644f4..d8f18a6afdf38b7fb7fe0782337880af61f699db 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
diff --git a/include/ns16550.h b/include/ns16550.h
index 22b89e4d6d19db7df724b1775d6aa386bc1c9818..701efeea855f3eb5d2564d85cf796bbb1279bfc0 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;
diff --git a/include/pci.h b/include/pci.h
index 298d0d43559954c6d255b7476f98eadb3ed78437..8aa6636cfbf85441376dfc2c5ae2dbb1651cbc54 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
@@ -1490,13 +1494,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
 	 *
@@ -1598,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
diff --git a/include/spl.h b/include/spl.h
index e4640f3830b04a7adfbcdd259b1aac047eb7bde4..c7cc2b0767cfcb18a76a49b5bd65eabedf2ef155 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -49,6 +49,72 @@ static inline bool u_boot_first_phase(void)
 	return false;
 }
 
+enum u_boot_phase {
+	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 */
+};
+
+/**
+ * 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_BOARD_F) {
+ *       ...
+ *    }
+ *
+ * @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
+	DECLARE_GLOBAL_DATA_PTR;
+
+	if (!(gd->flags & GD_FLG_RELOC))
+		return PHASE_BOARD_F;
+	else
+		return PHASE_BOARD_R;
+#endif
+}
+
 /* A string name for SPL or TPL */
 #ifdef CONFIG_SPL_BUILD
 # ifdef CONFIG_TPL_BUILD
diff --git a/lib/Kconfig b/lib/Kconfig
index 3da45a5ec3221f8ea80091e06d21a9723b45cf02..135f0b372b074270beab7450a542edeeef94124f 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 2fffd68f943cb9e207bc4218e26cc98b5b039e96..d248d8626cea1ee2951c9380bd749b0754fe8418 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
diff --git a/lib/display_options.c b/lib/display_options.c
index cff20f375523be26aceaa88801eaa3723cc21b60..ec16d75e0e4cf2a2444d4a3f1e0836f18c937445 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;
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 74430c8b2ffd219fd0b1099177f4ca4503eecaac..17736ce66554e0ce56e317480e7b12b64e73b399 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;
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 5a007d37091cc38c698f20a1f5d3ddd6e610215d..cb855354ae9308a94960363d83b1c2559acee5f3 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
diff --git a/test/dm/core.c b/test/dm/core.c
index edd55b05d6e293ebe9856b0e7da3d894a778fe79..f74c4308439e6ba08d2d615bc5f5f38ffde1e560 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;
diff --git a/test/dm/pci.c b/test/dm/pci.c
index c325f6600e70861002578b3862842a7b5015ba1a..fb93e4c78ae07077dc8473552c5ba39e16bcf3d4 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);
@@ -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);
diff --git a/test/dm/test-main.c b/test/dm/test-main.c
index 5d79ce641d7b6c4198f08f9d1f78b327ea80e341..72648162a917a4be80d8d76b547683ab5ed31e81 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)
@@ -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,16 +180,20 @@ 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);
 
+	/* 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);
 
diff --git a/tools/binman/README b/tools/binman/README
index b4f6392ab7455d8409d672bd42df0484b237cdd4..8e0f0a8c55b7d54a48f50aa0e712125dfa3e14ae 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<level> option to the call to binman:
+
+   make sandbox_defconfig
+   make BINMAN_VERBOSE=5
+
 
 History / Credits
 -----------------
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 9e7587864ce0d1a8b30f3a50adeac0232fc3cfc6..cb51bc2dd4663683d9df1915aab2cb263a09c808 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 == '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 == '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 == 'ls':
+                ListEntries(args.image, args.paths)
+
+            if args.cmd == 'extract':
+                ExtractEntries(args.image, args.filename, args.outdir, args.paths,
+                               not args.uncompressed)
+
+            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
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 6a2c6e0d92e5b0cb0fff2dcce436490f4e2cbc9f..fe8e1dd8a579c09db40e3bcb53b27403add97d5f 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -714,9 +714,27 @@ 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 entry
+
+        This reads data from the parent and extracts the piece that relates to
+        the given child.
+
+        Args:
+            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
+
+        Returns:
+            Data for the child (bytes)
+        """
+        pass
+
     def LoadData(self, decomp=True):
         data = self.ReadData(decomp)
         self.contents_size = len(data)
diff --git a/tools/binman/etype/image_header.py b/tools/binman/etype/image_header.py
index 4b69eda1a22bbf8c9d622bcfafc49b1d9c8581de..b9327dd799b7513cd914e2d50b06127ab7b23aa2 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):
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 5d34fc546afd7ea9140e530b2c4a25564a7b9285..8179daf5628da928346c853e375617c88ed0db5f 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 7b39a1ddcecc47396d313cf58519ffd227a07684..2beab7fd4d2d50ebdf9b2627005a1944cea78631 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):