diff --git a/Makefile b/Makefile
index a96c6ce81e07c3f4cb357cf39242393bb1c5a411..3000d30be23c708de27d6bab1eb7f0b4a9582bd8 100644
--- a/Makefile
+++ b/Makefile
@@ -806,6 +806,12 @@ else
 SPL_SIZE_CHECK =
 endif
 
+ifneq ($(CONFIG_TPL_SIZE_LIMIT),0)
+TPL_SIZE_CHECK = @$(call size_check,$@,$(CONFIG_TPL_SIZE_LIMIT))
+else
+TPL_SIZE_CHECK =
+endif
+
 # Statically apply RELA-style relocations (currently arm64 only)
 # This is useful for arm64 where static relocation needs to be performed on
 # the raw binary, but certain simulators only accept an ELF file (but don't
@@ -1806,6 +1812,7 @@ spl/boot.bin: spl/u-boot-spl
 tpl/u-boot-tpl.bin: tools prepare \
 		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb)
 	$(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all
+	$(TPL_SIZE_CHECK)
 
 TAG_SUBDIRS := $(patsubst %,$(srctree)/%,$(u-boot-dirs) include)
 
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 90b546e74100c2c5772a09ad79ecdbc2610f3f7c..31663714a0977045de073af480d1f901e148c343 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -385,6 +385,14 @@ static void setup_mtrr(void)
 	}
 }
 
+int x86_cpu_init_tpl(void)
+{
+	setup_cpu_features();
+	setup_identity();
+
+	return 0;
+}
+
 int x86_cpu_init_f(void)
 {
 	if (ll_boot_init())
diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
index a73b4d7c4597f7a5df030aa46d0e41b66fa08cc5..22cab2dd6cedf2956c294e543537c4a7f0b0b011 100644
--- a/arch/x86/cpu/start_from_spl.S
+++ b/arch/x86/cpu/start_from_spl.S
@@ -31,6 +31,7 @@ _start:
 
 	call	board_init_f_init_reserve
 
+	call	x86_cpu_reinit_f
 	xorl	%eax, %eax
 	call	board_init_f
 	call	board_init_f_r
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index feee0f915f6920e265a5103de58052cbb4070790..21a05dab7de8f4fa15c33b1ab3afdc89823db757 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -55,6 +55,7 @@ enum {
 	X86_SYSCON_PINCONF,	/* Intel x86 pin configuration */
 	X86_SYSCON_PMU,		/* Power Management Unit */
 	X86_SYSCON_SCU,		/* System Controller Unit */
+	X86_SYSCON_PUNIT,	/* Power unit */
 };
 
 struct cpuid_result {
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 17a4d344913ffbb4532ff03c4939368e89baf6c3..7f3ada06f6166b0916c79455511fe42864476248 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -76,6 +76,7 @@ struct arch_global_data {
 	uint8_t x86_mask;
 	uint32_t x86_device;
 	uint64_t tsc_base;		/* Initial value returned by rdtsc() */
+	bool tsc_inited;		/* true if tsc is ready for use */
 	unsigned long clock_rate;	/* Clock rate of timer in Hz */
 	void *new_fdt;			/* Relocated FDT */
 	uint32_t bist;			/* Built-in self test value */
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 2466ad2ad305cc1bef73ff5e511d74eb6dc9b7d4..3e5d56d0757d53748d84a87c158a024afcf2c64b 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -34,6 +34,15 @@ int x86_cpu_init_f(void);
  */
 int x86_cpu_reinit_f(void);
 
+/**
+ * x86_cpu_init_tpl() - Do the minimum possible CPU init
+ *
+ * This just sets up the CPU features and figured out the identity
+ *
+ * @return 0 (indicating success, to mimic cpu_init_f())
+ */
+int x86_cpu_init_tpl(void);
+
 int cpu_init_f(void);
 void setup_gdt(struct global_data *id, u64 *gdt_addr);
 /*
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 7623fc9ada0777d585f25d6e2d2f7842a304b93a..1677f80b25c23421435c213bdfeea046de981231 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -5,11 +5,15 @@
 
 #include <common.h>
 #include <debug_uart.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spl.h>
+#include <syscon.h>
 #include <asm/cpu.h>
+#include <asm/cpu_common.h>
 #include <asm/mrccache.h>
 #include <asm/mtrr.h>
+#include <asm/pci.h>
 #include <asm/processor.h>
 #include <asm/spl.h>
 #include <asm-generic/sections.h>
@@ -21,6 +25,32 @@ __weak int arch_cpu_init_dm(void)
 	return 0;
 }
 
+#ifdef CONFIG_TPL
+
+static int set_max_freq(void)
+{
+	if (cpu_get_burst_mode_state() == BURST_MODE_UNAVAILABLE) {
+		/*
+		 * Burst Mode has been factory-configured as disabled and is not
+		 * available in this physical processor package
+		 */
+		debug("Burst Mode is factory-disabled\n");
+		return -ENOENT;
+	}
+
+	/* Enable burst mode */
+	cpu_set_burst_mode(true);
+
+	/* Enable speed step */
+	cpu_set_eist(true);
+
+	/* Set P-State ratio */
+	cpu_set_p_state_to_turbo_ratio();
+
+	return 0;
+}
+#endif
+
 static int x86_spl_init(void)
 {
 #ifndef CONFIG_TPL
@@ -31,10 +61,16 @@ static int x86_spl_init(void)
 	 * place it immediately below CONFIG_SYS_TEXT_BASE.
 	 */
 	char *ptr = (char *)0x110000;
+#else
+	struct udevice *punit;
 #endif
 	int ret;
 
 	debug("%s starting\n", __func__);
+	if (IS_ENABLED(TPL))
+		ret = x86_cpu_reinit_f();
+	else
+		ret = x86_cpu_init_f();
 	ret = spl_init();
 	if (ret) {
 		debug("%s: spl_init() failed\n", __func__);
@@ -101,6 +137,14 @@ static int x86_spl_init(void)
 		return ret;
 	}
 	mtrr_commit(true);
+#else
+	ret = syscon_get_by_driver_data(X86_SYSCON_PUNIT, &punit);
+	if (ret)
+		debug("Could not find PUNIT (err=%d)\n", ret);
+
+	ret = set_max_freq();
+	if (ret)
+		debug("Failed to set CPU frequency (err=%d)\n", ret);
 #endif
 
 	return 0;
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index d70f590541c68bf03efad8d9e17b4ef66d4fee20..784e3a02def1279890fab986632e1005ed33b27c 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <debug_uart.h>
+#include <dm.h>
 #include <spl.h>
 #include <asm/cpu.h>
 #include <asm/mtrr.h>
@@ -23,6 +24,11 @@ static int x86_tpl_init(void)
 	int ret;
 
 	debug("%s starting\n", __func__);
+	ret = x86_cpu_init_tpl();
+	if (ret) {
+		debug("%s: x86_cpu_init_tpl() failed\n", __func__);
+		return ret;
+	}
 	ret = spl_init();
 	if (ret) {
 		debug("%s: spl_init() failed\n", __func__);
@@ -39,11 +45,6 @@ static int x86_tpl_init(void)
 		return ret;
 	}
 	preloader_console_init();
-	ret = print_cpuinfo();
-	if (ret) {
-		debug("%s: print_cpuinfo() failed\n", __func__);
-		return ret;
-	}
 
 	return 0;
 }
@@ -106,7 +107,7 @@ int spl_spi_load_image(void)
 
 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);
+	debug("Jumping to U-Boot SPL at %lx\n", (ulong)spl_image->entry_point);
 	jump_to_spl(spl_image->entry_point);
 	hang();
 }
@@ -115,3 +116,27 @@ void spl_board_init(void)
 {
 	preloader_console_init();
 }
+
+#if !CONFIG_IS_ENABLED(PCI)
+/*
+ * This is a fake PCI bus for TPL when it doesn't have proper PCI. It is enough
+ * to bind the devices on the PCI bus, some of which have early-regs properties
+ * providing fixed BARs. Individual drivers program these BARs themselves so
+ * that they can access the devices. The BARs are allocated statically in the
+ * device tree.
+ *
+ * Once SPL is running it enables PCI properly, but does not auto-assign BARs
+ * for devices, so the TPL BARs continue to be used. Once U-Boot starts it does
+ * the auto allocation (after relocation).
+ */
+static const struct udevice_id tpl_fake_pci_ids[] = {
+	{ .compatible = "pci-x86" },
+	{ }
+};
+
+U_BOOT_DRIVER(pci_x86) = {
+	.name	= "pci_x86",
+	.id	= UCLASS_SIMPLE_BUS,
+	.of_match = tpl_fake_pci_ids,
+};
+#endif
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 86d7edfee1b838091f6e8f7cee72cd7d2d3519e5..c661809923ab8d8c1119c9edac1cd57b260c59bf 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1232,6 +1232,14 @@ config TPL
 
 if TPL
 
+config TPL_SIZE_LIMIT
+	hex "Maximum size of TPL image"
+	depends on TPL
+	default 0
+	help
+	  Specifies the maximum length of the U-Boot TPL image.
+	  If this value is zero, it is ignored.
+
 config TPL_HANDOFF
 	bool "Pass hand-off information from TPL to SPL and U-Boot proper"
 	depends on HANDOFF && TPL_BLOBLIST
diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
index a38e58e4d294ad0d3f275c5557408d2dcdb39bff..557957d2a166903110ca32c36b7b80d1cb112773 100644
--- a/doc/driver-model/of-plat.rst
+++ b/doc/driver-model/of-plat.rst
@@ -269,7 +269,7 @@ For example:
     };
 
     U_BOOT_DRIVER(mmc_drv) = {
-            .name           = "mmc",
+            .name           = "vendor_mmc",  /* matches compatible string */
             .id             = UCLASS_MMC,
             .of_match       = mmc_ids,
             .ofdata_to_platdata = mmc_ofdata_to_platdata,
diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c
index 16473ec7a0b9d5e36d3ca270c98e8b23060f48a7..6b610ff8231989c5cf06ffd8de3d116b54816eb6 100644
--- a/drivers/spi/sandbox_spi.c
+++ b/drivers/spi/sandbox_spi.c
@@ -122,11 +122,22 @@ static int sandbox_cs_info(struct udevice *bus, uint cs,
 	return 0;
 }
 
+static int sandbox_spi_get_mmap(struct udevice *dev, ulong *map_basep,
+				uint *map_sizep, uint *offsetp)
+{
+	*map_basep = 0x1000;
+	*map_sizep = 0x2000;
+	*offsetp = 0x100;
+
+	return 0;
+}
+
 static const struct dm_spi_ops sandbox_spi_ops = {
 	.xfer		= sandbox_spi_xfer,
 	.set_speed	= sandbox_spi_set_speed,
 	.set_mode	= sandbox_spi_set_mode,
 	.cs_info	= sandbox_cs_info,
+	.get_mmap	= sandbox_spi_get_mmap,
 };
 
 static const struct udevice_id sandbox_spi_ids[] = {
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 947516073ea99650b1703a9fc5fcc854b5496a81..665611f7e23a3337720c2589e73c55fef74efe77 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -92,6 +92,20 @@ int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
 }
 
+int dm_spi_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
+		    uint *offsetp)
+{
+	struct udevice *bus = dev->parent;
+	struct dm_spi_ops *ops = spi_get_ops(bus);
+
+	if (bus->uclass->uc_drv->id != UCLASS_SPI)
+		return -EOPNOTSUPP;
+	if (!ops->get_mmap)
+		return -ENOSYS;
+
+	return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
+
 int spi_claim_bus(struct spi_slave *slave)
 {
 	return log_ret(dm_spi_claim_bus(slave->dev));
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index 919caba8a14ecb6776fb751549ece663c7f071ca..637c8ff25a5cab47aee23201d28a0ef26de11b41 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -394,7 +394,7 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count)
 
 static void tsc_timer_ensure_setup(bool early)
 {
-	if (gd->arch.tsc_base)
+	if (gd->arch.tsc_inited)
 		return;
 	gd->arch.tsc_base = rdtsc();
 
@@ -425,6 +425,7 @@ static void tsc_timer_ensure_setup(bool early)
 done:
 		gd->arch.clock_rate = fast_calibrate * 1000000;
 	}
+	gd->arch.tsc_inited = true;
 }
 
 static int tsc_timer_probe(struct udevice *dev)
@@ -461,6 +462,8 @@ unsigned long notrace timer_early_get_rate(void)
 
 u64 notrace timer_early_get_count(void)
 {
+	tsc_timer_ensure_setup(true);
+
 	return rdtsc() - gd->arch.tsc_base;
 }
 
diff --git a/include/cbfs.h b/include/cbfs.h
index 6d4c4d4b065a7b0295ae8fbd3cf0f1e8abea2ebf..f3bc8ca24afe573405ec39d428649898c476ad3b 100644
--- a/include/cbfs.h
+++ b/include/cbfs.h
@@ -72,13 +72,13 @@ struct cbfs_fileheader {
 
 struct cbfs_cachenode {
 	struct cbfs_cachenode *next;
-	u32 type;
 	void *data;
-	u32 data_length;
 	char *name;
+	u32 type;
+	u32 data_length;
 	u32 name_length;
 	u32 attributes_offset;
-} __packed;
+};
 
 extern enum cbfs_result file_cbfs_result;
 
diff --git a/include/spi.h b/include/spi.h
index 3f79168df30ab70756725bded35342288824054c..6fbb4336ce381f9fa9a38e72546983102baf1e79 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -462,6 +462,19 @@ struct dm_spi_ops {
 	 *	   is invalid, other -ve value on error
 	 */
 	int (*cs_info)(struct udevice *bus, uint cs, struct spi_cs_info *info);
+
+	/**
+	 * get_mmap() - Get memory-mapped SPI
+	 *
+	 * @dev:	The SPI flash slave device
+	 * @map_basep:	Returns base memory address for mapped SPI
+	 * @map_sizep:	Returns size of mapped SPI
+	 * @offsetp:	Returns start offset of SPI flash where the map works
+	 *	correctly (offsets before this are not visible)
+	 * @return 0 if OK, -EFAULT if memory mapping is not available
+	 */
+	int (*get_mmap)(struct udevice *dev, ulong *map_basep,
+			uint *map_sizep, uint *offsetp);
 };
 
 struct dm_spi_emul_ops {
@@ -650,6 +663,20 @@ void dm_spi_release_bus(struct udevice *dev);
 int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		const void *dout, void *din, unsigned long flags);
 
+/**
+ * spi_get_mmap() - Get memory-mapped SPI
+ *
+ * @dev:	SPI slave device to check
+ * @map_basep:	Returns base memory address for mapped SPI
+ * @map_sizep:	Returns size of mapped SPI
+ * @offsetp:	Returns start offset of SPI flash where the map works
+ *	correctly (offsets before this are not visible)
+ * @return 0 if OK, -ENOSYS if no operation, -EFAULT if memory mapping is not
+ *	available
+ */
+int dm_spi_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
+		    uint *offsetp);
+
 /* Access the operations for a SPI device */
 #define spi_get_ops(dev)	((struct dm_spi_ops *)(dev)->driver->ops)
 #define spi_emul_get_ops(dev)	((struct dm_spi_emul_ops *)(dev)->driver->ops)
diff --git a/include/spl.h b/include/spl.h
index b5387ef273df31db0601aed37092f34087f54baa..08ffddac29f27a5495881dbfc58258e220df3ed7 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -332,14 +332,14 @@ struct spl_image_loader {
  */
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 #define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \
-	SPL_LOAD_IMAGE(_method ## _priority ## _boot_device) = { \
+	SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \
 		.name = _name, \
 		.boot_device = _boot_device, \
 		.load_image = _method, \
 	}
 #else
 #define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \
-	SPL_LOAD_IMAGE(_method ## _priority ## _boot_device) = { \
+	SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \
 		.boot_device = _boot_device, \
 		.load_image = _method, \
 	}
diff --git a/test/dm/sf.c b/test/dm/sf.c
index 3788d59052e448e878a734d2ba886fc97232e6d0..65aab4f2e9caf189fe886eb2f1aa616b4b12863d 100644
--- a/test/dm/sf.c
+++ b/test/dm/sf.c
@@ -23,6 +23,9 @@ static int dm_test_spi_flash(struct unit_test_state *uts)
 	int full_size = 0x200000;
 	int size = 0x10000;
 	u8 *src, *dst;
+	uint map_size;
+	ulong map_base;
+	uint offset;
 	int i;
 
 	src = map_sysmem(0x20000, full_size);
@@ -54,6 +57,12 @@ static int dm_test_spi_flash(struct unit_test_state *uts)
 	sandbox_sf_set_block_protect(emul, 0);
 	ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
 
+	/* Check mapping */
+	ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset));
+	ut_asserteq(0x1000, map_base);
+	ut_asserteq(0x2000, map_size);
+	ut_asserteq(0x100, offset);
+
 	/*
 	 * Since we are about to destroy all devices, we must tell sandbox
 	 * to forget the emulation device
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
index bce224459690d0da93f338a548e0047db4d2a32c..10994335217c572bb4f16b5669d716c34568d1bb 100644
--- a/tools/binman/README.entries
+++ b/tools/binman/README.entries
@@ -444,6 +444,39 @@ See README.x86 for information about x86 binary blobs.
 
 
 
+Entry: intel-fsp-s: Entry containing Intel Firmware Support Package (FSP) silicon init
+--------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains a binary blob which is used on some devices to set up
+the silicon. U-Boot executes this code in U-Boot proper after SDRAM is
+running, so that it can make full use of memory. Documentation is typically
+not available in sufficient detail to allow U-Boot do this this itself.
+
+An example filename is 'fsp_s.bin'
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-fsp-t: Entry containing Intel Firmware Support Package (FSP) temp ram init
+---------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of file to read into entry
+
+This file contains a binary blob which is used on some devices to set up
+temporary memory (Cache-as-RAM or CAR). U-Boot executes this code in TPL so
+that it has access to memory for its stack and initial storage.
+
+An example filename is 'fsp_t.bin'
+
+See README.x86 for information about x86 binary blobs.
+
+
+
 Entry: intel-ifwi: Entry containing an Intel Integrated Firmware Image (IFWI) file
 ----------------------------------------------------------------------------------
 
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 7bc7cf61b5d83721cbd73e093fd40d6619889520..0c1a5b44b669a39e46c8cf1f575ac5b89ad0daea 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -135,9 +135,7 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
 
             # Look up the symbol in our entry tables.
             value = section.LookupSymbol(name, sym.weak, msg)
-            if value is not None:
-                value += base.address
-            else:
+            if value is None:
                 value = -1
                 pack_string = pack_string.lower()
             value_bytes = struct.pack(pack_string, value)
diff --git a/tools/binman/etype/intel_fsp_m.py b/tools/binman/etype/intel_fsp_m.py
index 2d6b2b6621b692151a2104db8a6f7c8eca3d4a32..bb1de73e4145349806ba783715407ef541efe3ef 100644
--- a/tools/binman/etype/intel_fsp_m.py
+++ b/tools/binman/etype/intel_fsp_m.py
@@ -2,7 +2,7 @@
 # Copyright 2019 Google LLC
 # Written by Simon Glass <sjg@chromium.org>
 #
-# Entry-type module for Intel Firmware Support Package binary blob (T section)
+# Entry-type module for Intel Firmware Support Package binary blob (M section)
 #
 
 from entry import Entry
diff --git a/tools/binman/etype/intel_fsp_s.py b/tools/binman/etype/intel_fsp_s.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d6900d1fba2cb365484c4cafb11cb6c544f51bf
--- /dev/null
+++ b/tools/binman/etype/intel_fsp_s.py
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2019 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for Intel Firmware Support Package binary blob (S section)
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_fsp_s(Entry_blob):
+    """Entry containing Intel Firmware Support Package (FSP) silicon init
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains a binary blob which is used on some devices to set up
+    the silicon. U-Boot executes this code in U-Boot proper after SDRAM is
+    running, so that it can make full use of memory. Documentation is typically
+    not available in sufficient detail to allow U-Boot do this this itself.
+
+    An example filename is 'fsp_s.bin'
+
+    See README.x86 for information about x86 binary blobs.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/intel_fsp_t.py b/tools/binman/etype/intel_fsp_t.py
new file mode 100644
index 0000000000000000000000000000000000000000..813a81f2e66e70b021cec239344062c7c0d24f4a
--- /dev/null
+++ b/tools/binman/etype/intel_fsp_t.py
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2019 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for Intel Firmware Support Package binary blob (T section)
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_fsp_t(Entry_blob):
+    """Entry containing Intel Firmware Support Package (FSP) temp ram init
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains a binary blob which is used on some devices to set up
+    temporary memory (Cache-as-RAM or CAR). U-Boot executes this code in TPL so
+    that it has access to memory for its stack and initial storage.
+
+    An example filename is 'fsp_t.bin'
+
+    See README.x86 for information about x86 binary blobs.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 7000de9d420f7b61c61eb099debdf20ee24c4658..494e218cbc3a29a7acb37979816d6274a0fda17d 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -73,6 +73,8 @@ FILES_DATA            = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
 COMPRESS_DATA         = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
 REFCODE_DATA          = b'refcode'
 FSP_M_DATA            = b'fsp_m'
+FSP_S_DATA            = b'fsp_s'
+FSP_T_DATA            = b'fsp_t'
 
 # The expected size for the device tree in some tests
 EXTRACT_DTB_SIZE = 0x3c9
@@ -149,6 +151,8 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
         TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
         TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
+        TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
+        TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
 
         cls._elf_testdir = os.path.join(cls._indir, 'elftest')
         elf_test.BuildElfTestFiles(cls._elf_testdir)
@@ -3332,6 +3336,15 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('152_intel_fsp_m.dts')
         self.assertEqual(FSP_M_DATA, data[:len(FSP_M_DATA)])
 
+    def testPackFspS(self):
+        """Test that an image with a FSP silicon-init binary can be created"""
+        data = self._DoReadFile('153_intel_fsp_s.dts')
+        self.assertEqual(FSP_S_DATA, data[:len(FSP_S_DATA)])
+
+    def testPackFspT(self):
+        """Test that an image with a FSP temp-ram-init binary can be created"""
+        data = self._DoReadFile('154_intel_fsp_t.dts')
+        self.assertEqual(FSP_T_DATA, data[:len(FSP_T_DATA)])
 
 
 if __name__ == "__main__":
diff --git a/tools/binman/test/153_intel_fsp_s.dts b/tools/binman/test/153_intel_fsp_s.dts
new file mode 100644
index 0000000000000000000000000000000000000000..579618a8fa3f4340808317fdbb86466bb809e265
--- /dev/null
+++ b/tools/binman/test/153_intel_fsp_s.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <16>;
+
+		intel-fsp-s {
+			filename = "fsp_s.bin";
+		};
+	};
+};
diff --git a/tools/binman/test/154_intel_fsp_t.dts b/tools/binman/test/154_intel_fsp_t.dts
new file mode 100644
index 0000000000000000000000000000000000000000..8da749c1574738ecb655d0134b6333968bd0d166
--- /dev/null
+++ b/tools/binman/test/154_intel_fsp_t.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <16>;
+
+		intel-fsp-t {
+			filename = "fsp_t.bin";
+		};
+	};
+};
diff --git a/tools/binman/test/u_boot_binman_syms.lds b/tools/binman/test/u_boot_binman_syms.lds
index 926df873cb70b2aeeb55ab17b89ae2e84db93d74..825fc3f649f78f35c8dfb5530621f128e02a717a 100644
--- a/tools/binman/test/u_boot_binman_syms.lds
+++ b/tools/binman/test/u_boot_binman_syms.lds
@@ -9,7 +9,7 @@ ENTRY(_start)
 
 SECTIONS
 {
-	. = 0x00000000;
+	. = 0x00000010;
 	_start = .;
 
 	. = ALIGN(4);