diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index 53bce7d5a04c19a279bd72b4d6f829235b0b39e5..559ae3d3bc504ae208f307dc86587899ba709585 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -36,7 +36,7 @@ ENTRY(tsp_entrypoint)
 
 
 MEMORY {
-    RAM (rwx): ORIGIN = TZDRAM_BASE, LENGTH = TZDRAM_SIZE
+    RAM (rwx): ORIGIN = TSP_SEC_MEM_BASE, LENGTH = TSP_SEC_MEM_SIZE
 }
 
 
@@ -113,11 +113,11 @@ SECTIONS
         __COHERENT_RAM_END__ = .;
     } >RAM
 
-    __BL2_END__ = .;
+    __BL32_END__ = .;
 
     __BSS_SIZE__ = SIZEOF(.bss);
     __COHERENT_RAM_UNALIGNED_SIZE__ =
         __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
 
-    ASSERT(. <= TZDRAM_BASE + (1 << 21), "BL32 image does not fit in the first 2MB of Trusted DRAM.")
+    ASSERT(. <= BL32_LIMIT, "BL3-2 image does not fit.")
 }
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index df0176e33e57be63cf4eb211db9d2f95ee1edefa..eb203a71bd64b4879861f9f93f7d3f9ab8e6abdc 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -191,9 +191,36 @@ constants defined. In the ARM FVP port, this file is found in
     image. Must be aligned on a page-size boundary.
 
 *   **#define : NS_IMAGE_OFFSET**
+
     Defines the base address in non-secure DRAM where BL2 loads the BL3-3 binary
     image. Must be aligned on a page-size boundary.
 
+If the BL3-2 image is supported by the platform, the following constants must
+be defined as well:
+
+*   **#define : TSP_SEC_MEM_BASE**
+
+    Defines the base address of the secure memory used by the BL3-2 image on the
+    platform.
+
+*   **#define : TSP_SEC_MEM_SIZE**
+
+    Defines the size of the secure memory used by the BL3-2 image on the
+    platform.
+
+*   **#define : BL32_BASE**
+
+    Defines the base address in secure memory where BL2 loads the BL3-2 binary
+    image. Must be inside the secure memory identified by `TSP_SEC_MEM_BASE` and
+    `TSP_SEC_MEM_SIZE` constants. Must also be aligned on a page-size boundary.
+
+*   **#define : BL32_LIMIT**
+
+    Defines the maximum address that the BL3-2 image can occupy. Must be inside
+    the secure memory identified by `TSP_SEC_MEM_BASE` and `TSP_SEC_MEM_SIZE`
+    constants.
+
+
 ### File : platform_macros.S [mandatory]
 
 Each platform must export a file of this name with the following
diff --git a/docs/user-guide.md b/docs/user-guide.md
index e7f0df54cea27a6a59a78dd7647c662769394b7d..a6256efad2340f747a23065c4628fd7b938d891c 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -89,7 +89,8 @@ To build the software for the FVPs, follow these steps:
     By default this produces a release version of the build. To produce a debug
     version instead, refer to the "Debugging options" section below. UEFI can be
     used as the BL3-3 image, refer to the "Obtaining the normal world software"
-    section below.
+    section below. By default this won't compile the TSP in, refer to the
+    "Building the Test Secure Payload" section below.
 
     The build process creates products in a `build` directory tree, building
     the objects and binaries for each boot loader stage in separate
@@ -243,6 +244,48 @@ Extra debug options can be passed to the build system by setting `CFLAGS`:
 NOTE: The Foundation FVP does not provide a debugger interface.
 
 
+### Building the Test Secure Payload
+
+The TSP is coupled with a companion runtime service in the BL3-1 firmware,
+called the TSPD. Therefore, if you intend to use the TSP, the BL3-1 image
+must be recompiled as well. For more information on SPs and SPDs, see the
+"Secure-EL1 Payloads and Dispatchers" section in the [Firmware Design].
+
+First clean the Trusted Firmware build directory to get rid of any previous
+BL3-1 binary. Then to build the TSP image and include it into the FIP use:
+
+    CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+    BL33=<path-to>/<bl33_image>                               \
+    make PLAT=fvp SPD=tspd all fip
+
+An additional boot loader binary file is created in the `build` directory:
+
+    *   `build/<platform>/<build-type>/bl32.bin`
+
+The Firmware Package contains this new image:
+
+    Firmware Image Package ToC:
+    ---------------------------
+    - Trusted Boot Firmware BL2: offset=0xD8, size=0x6000
+      file: './build/fvp/release/bl2.bin'
+    - EL3 Runtime Firmware BL3-1: offset=0x60D8, size=0x9000
+      file: './build/fvp/release/bl31.bin'
+    - Secure Payload BL3-2 (Trusted OS): offset=0xF0D8, size=0x3000
+      file: './build/fvp/release/bl32.bin'
+    - Non-Trusted Firmware BL3-3: offset=0x120D8, size=0x280000
+      file: '../FVP_AARCH64_EFI.fd'
+    ---------------------------
+    Creating "build/fvp/release/fip.bin"
+
+On FVP, the TSP binary runs from Trusted SRAM by default. It is also possible
+to run it from Trusted DRAM. This is controlled by the build configuration
+`TSP_RAM_LOCATION`:
+
+    CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+    BL33=<path-to>/<bl33_image>                               \
+    make PLAT=fvp SPD=tspd TSP_RAM_LOCATION=tdram all fip
+
+
 ### Checking source code style
 
 When making changes to the source for submission to the project, the source
diff --git a/plat/fvp/bl2_plat_setup.c b/plat/fvp/bl2_plat_setup.c
index 38525eac5d7c834a1e1b34b60662e6ad616cac72..8b17fdd3991ed5ab50574be0c329f8b2da9ce754 100644
--- a/plat/fvp/bl2_plat_setup.c
+++ b/plat/fvp/bl2_plat_setup.c
@@ -98,11 +98,13 @@ bl31_params_t *bl2_plat_get_bl31_params(void)
 {
 	bl2_to_bl31_params_mem_t *bl31_params_mem;
 
+#if TSP_RAM_LOCATION_ID == TSP_IN_TZDRAM
 	/*
 	 * Ensure that the secure DRAM memory used for passing BL31 arguments
 	 * does not overlap with the BL32_BASE.
 	 */
 	assert(BL32_BASE > PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t));
+#endif
 
 	/*
 	 * Allocate the memory for all the arguments that needs to
@@ -261,15 +263,13 @@ extern void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
 {
 	/*
 	 * Populate the extents of memory available for loading BL32.
-	 * TODO: We are temporarily executing BL2 from TZDRAM;
-	 * will eventually move to Trusted SRAM
 	 */
 	bl32_meminfo->total_base = BL32_BASE;
 	bl32_meminfo->free_base = BL32_BASE;
 	bl32_meminfo->total_size =
-			(TZDRAM_BASE + TZDRAM_SIZE) - BL32_BASE;
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
 	bl32_meminfo->free_size =
-			(TZDRAM_BASE + TZDRAM_SIZE) - BL32_BASE;
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
 	bl32_meminfo->attr = BOT_LOAD;
 	bl32_meminfo->next = 0;
 }
diff --git a/plat/fvp/platform.h b/plat/fvp/platform.h
index 4c8d6064a1b6be5a2731a5e52e7de8ceb84b484a..e48a2c9d555687e153b22a82be3d309c89b6c224 100644
--- a/plat/fvp/platform.h
+++ b/plat/fvp/platform.h
@@ -238,17 +238,35 @@
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
-#define BL2_BASE			0x0402D000
+#define BL2_BASE			(TZRAM_BASE + TZRAM_SIZE - 0xc000)
 
 /*******************************************************************************
  * BL31 specific defines.
  ******************************************************************************/
-#define BL31_BASE			0x0400C000
+#define BL31_BASE			(TZRAM_BASE + 0x6000)
 
 /*******************************************************************************
  * BL32 specific defines.
  ******************************************************************************/
-#define BL32_BASE			(TZDRAM_BASE + 0x2000)
+/*
+ * On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+ */
+#define TSP_IN_TZRAM			0
+#define TSP_IN_TZDRAM			1
+
+#if TSP_RAM_LOCATION_ID == TSP_IN_TZRAM
+# define TSP_SEC_MEM_BASE		TZRAM_BASE
+# define TSP_SEC_MEM_SIZE		TZRAM_SIZE
+# define BL32_BASE			(TZRAM_BASE + TZRAM_SIZE - 0x1c000)
+# define BL32_LIMIT			BL2_BASE
+#elif TSP_RAM_LOCATION_ID == TSP_IN_TZDRAM
+# define TSP_SEC_MEM_BASE		TZDRAM_BASE
+# define TSP_SEC_MEM_SIZE		TZDRAM_SIZE
+# define BL32_BASE			(TZDRAM_BASE + 0x2000)
+# define BL32_LIMIT			(TZDRAM_BASE + (1 << 21))
+#else
+# error "Unsupported TSP_RAM_LOCATION_ID value"
+#endif
 
 /*******************************************************************************
  * Platform specific page table and MMU setup constants
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
index 4de001bcb5f3f86eb6f86baefe7aeb083945c0db..82bafed6f74d25e721bc67a12496d40ab06095a2 100644
--- a/plat/fvp/platform.mk
+++ b/plat/fvp/platform.mk
@@ -28,6 +28,21 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+# On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+# Trusted SRAM is the default.
+TSP_RAM_LOCATION	:=	tsram
+
+ifeq (${TSP_RAM_LOCATION}, tsram)
+  TSP_RAM_LOCATION_ID := TSP_IN_TZRAM
+else ifeq (${TSP_RAM_LOCATION}, tdram)
+  TSP_RAM_LOCATION_ID := TSP_IN_TZDRAM
+else
+  $(error "Unsupported TSP_RAM_LOCATION value")
+endif
+
+# Process TSP_RAM_LOCATION_ID flag
+$(eval $(call add_define,TSP_RAM_LOCATION_ID))
+
 PLAT_INCLUDES		:=	-Iplat/fvp/include/
 
 PLAT_BL_COMMON_SOURCES	:=	drivers/arm/pl011/pl011.c			\