diff --git a/Makefile b/Makefile
index fe18bc0ea4ade881a953b5271c33b49757e42d0e..fe757984c2d06baf2bf213201ac65895a614c675 100644
--- a/Makefile
+++ b/Makefile
@@ -383,6 +383,17 @@ ifdef SCP_BL2
         NEED_SCP_BL2		:=	yes
 endif
 
+# For AArch32, BL31 is not currently supported.
+ifneq (${ARCH},aarch32)
+    ifdef BL31_SOURCES
+        # When booting an EL3 payload, there is no need to compile the BL31 image nor
+        # put it in the FIP.
+        ifndef EL3_PAYLOAD_BASE
+            NEED_BL31 := yes
+        endif
+    endif
+endif
+
 # Process TBB related flags
 ifneq (${GENERATE_COT},0)
         # Common cert_create options
@@ -434,17 +445,11 @@ NEED_BL2U := yes
 include bl2u/bl2u.mk
 endif
 
-# For AArch32, BL31 is not currently supported.
-ifneq (${ARCH},aarch32)
+ifeq (${NEED_BL31},yes)
 ifdef BL31_SOURCES
-# When booting an EL3 payload, there is no need to compile the BL31 image nor
-# put it in the FIP.
-ifndef EL3_PAYLOAD_BASE
-NEED_BL31 := yes
 include bl31/bl31.mk
 endif
 endif
-endif
 
 ################################################################################
 # Build options checks
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index fc44d5248897dbc7381b84a55a53f5294523d34c..932597312c56df6c8818e624f441d52ddf3f3f54 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -110,6 +110,10 @@ SECTIONS
         __DATA_END__ = .;
     } >RAM
 
+#ifdef BL32_PROGBITS_LIMIT
+    ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.")
+#endif
+
     stacks (NOLOAD) : {
         __STACKS_START__ = .;
         *(tzfw_normal_stacks)
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 79d660d0251fea3787e9ef04adabba2f47bb13c7..138ed8b3d764545b18ccb634840df44cf6ca5a22 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -1212,7 +1212,7 @@ corrupted binaries.
 
           make ARCH=aarch64 PLAT=juno LOAD_IMAGE_V2=1 JUNO_AARCH32_EL3_RUNTIME=1 \
           BL33=<path-to-juno32-oe-uboot>/SOFTWARE/bl33-uboot.bin \
-          SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin SPD=tspd \
+          SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin \
           BL32=<path-to-bl32>/bl32.bin all fip
 
 The resulting BL1 and FIP images may be found in:
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 97a1af4bff6623e5626d12dbc6aa7603a1d7a9df..68f4a0ec0905fc66109026e9fcfbf9ff72c56f25 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -96,6 +96,14 @@
 #define PLAT_ARM_MAX_BL31_SIZE		0x1D000
 #endif
 
+#ifdef AARCH32
+/*
+ * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
+ * Payload.
+ */
+# define PLAT_ARM_MAX_BL32_SIZE		0x1D000
+#endif
+
 #endif /* ARM_BOARD_OPTIMISE_MEM */
 
 #define MAX_IO_DEVICES			3
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index b8955afcc48320b7495f7fec0abb9b5b4661e5db..7887525992705e9811fe8aeda876c33a64d01d82 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -326,14 +326,21 @@
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
-#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
+#if ARM_BL31_IN_DRAM
 /*
- * For AArch32 BL31 is not applicable.
  * For AArch64 BL31 is loaded in the DRAM.
  * Put BL2 just below BL1.
  */
 #define BL2_BASE			(BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
 #define BL2_LIMIT			BL1_RW_BASE
+
+#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
+/*
+ * Put BL2 just below BL32.
+ */
+#define BL2_BASE			(BL32_BASE - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_LIMIT			BL32_BASE
+
 #else
 /*
  * Put BL2 just below BL31.
@@ -370,76 +377,86 @@
 #define BL31_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 #endif
 
+#if defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
 /*******************************************************************************
- * BL32 specific defines.
+ * BL32 specific defines for EL3 runtime in AArch32 mode
+ ******************************************************************************/
+# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME
+/* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM to BL32 */
+#  define BL32_BASE			ARM_BL_RAM_BASE
+#  define BL32_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+# else
+/* Put BL32 at the top of the Trusted SRAM.*/
+#  define BL32_BASE			(ARM_BL_RAM_BASE +		\
+						ARM_BL_RAM_SIZE -	\
+						PLAT_ARM_MAX_BL32_SIZE)
+#  define BL32_PROGBITS_LIMIT		BL1_RW_BASE
+#  define BL32_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */
+
+#else
+/*******************************************************************************
+ * BL32 specific defines for EL3 runtime in AArch64 mode
  ******************************************************************************/
 /*
  * On ARM standard platforms, the TSP can execute from Trusted SRAM,
  * Trusted DRAM (if available) or the DRAM region secured by the TrustZone
  * controller.
  */
-#if ENABLE_SPM
-# define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
-# define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
-# define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
-# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+# if ENABLE_SPM
+#  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
+#  define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
-#elif ARM_BL31_IN_DRAM
-# define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
+# elif ARM_BL31_IN_DRAM
+#  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
-# define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE -	\
+#  define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE -	\
 						PLAT_ARM_MAX_BL31_SIZE)
-# define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE +	\
+#  define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
-# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+#  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
-# define TSP_SEC_MEM_BASE		ARM_BL_RAM_BASE
-# define TSP_SEC_MEM_SIZE		ARM_BL_RAM_SIZE
-# define TSP_PROGBITS_LIMIT		BL2_BASE
-# define BL32_BASE			ARM_BL_RAM_BASE
-# define BL32_LIMIT			BL31_BASE
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
-# define TSP_SEC_MEM_BASE		PLAT_ARM_TRUSTED_DRAM_BASE
-# define TSP_SEC_MEM_SIZE		PLAT_ARM_TRUSTED_DRAM_SIZE
-# define BL32_BASE			PLAT_ARM_TRUSTED_DRAM_BASE
-# define BL32_LIMIT			(PLAT_ARM_TRUSTED_DRAM_BASE	\
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
+#  define TSP_SEC_MEM_BASE		ARM_BL_RAM_BASE
+#  define TSP_SEC_MEM_SIZE		ARM_BL_RAM_SIZE
+#  define TSP_PROGBITS_LIMIT		BL2_BASE
+#  define BL32_BASE			ARM_BL_RAM_BASE
+#  define BL32_LIMIT			BL31_BASE
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
+#  define TSP_SEC_MEM_BASE		PLAT_ARM_TRUSTED_DRAM_BASE
+#  define TSP_SEC_MEM_SIZE		PLAT_ARM_TRUSTED_DRAM_SIZE
+#  define BL32_BASE			PLAT_ARM_TRUSTED_DRAM_BASE
+#  define BL32_LIMIT			(PLAT_ARM_TRUSTED_DRAM_BASE	\
 						+ (1 << 21))
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
-# define TSP_SEC_MEM_BASE		ARM_AP_TZC_DRAM1_BASE
-# define TSP_SEC_MEM_SIZE		ARM_AP_TZC_DRAM1_SIZE
-# define BL32_BASE			ARM_AP_TZC_DRAM1_BASE
-# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
+#  define TSP_SEC_MEM_BASE		ARM_AP_TZC_DRAM1_BASE
+#  define TSP_SEC_MEM_SIZE		ARM_AP_TZC_DRAM1_SIZE
+#  define BL32_BASE			ARM_AP_TZC_DRAM1_BASE
+#  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
-#else
-# error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
-#endif
+# else
+#  error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
+# endif
+#endif /* AARCH32 || JUNO_AARCH32_EL3_RUNTIME */
 
 /*
  * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no
  * SPD and no SPM, as they are the only ones that can be used as BL32.
  */
-#ifndef AARCH32
+#if !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME)
 # if defined(SPD_none) && !ENABLE_SPM
 #  undef BL32_BASE
-# endif
-#endif
+# endif /* defined(SPD_none) && !ENABLE_SPM */
+#endif /* !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) */
 
 /*******************************************************************************
  * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
  ******************************************************************************/
 #define BL2U_BASE			BL2_BASE
-#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
-/*
- * For AArch32 BL31 is not applicable.
- * For AArch64 BL31 is loaded in the DRAM.
- * BL2U extends up to BL1.
- */
-#define BL2U_LIMIT			BL1_RW_BASE
-#else
-/* BL2U extends up to BL31. */
-#define BL2U_LIMIT			BL31_BASE
-#endif
+#define BL2U_LIMIT			BL2_LIMIT
+
 #define NS_BL2U_BASE			ARM_NS_DRAM1_BASE
 #define NS_BL1U_BASE			(PLAT_ARM_NVM_BASE + 0x03EB8000)
 
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index b13afe488f72b3c2505216b312ef01696e4ad17e..6e6e2739628a9e8189bd6769e9ef6240009a9c40 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -77,6 +77,7 @@ ifneq (${SCP_BL2},)
 endif
 
 ifeq (${ARCH},aarch64)
+ifeq (${NEED_BL31},yes)
 # Add the BL31 CoT (key cert + img cert + image)
 $(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\
              $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true)))
@@ -86,6 +87,7 @@ $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
 $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert))
 $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
 endif
+endif
 
 # Add the BL32 CoT (key cert + img cert + image)
 ifeq (${NEED_BL32},yes)
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index ccc7771e59c80cdbbf86fec6dadc464a278aed31..e475ece5a4917914a6f029b1c2dabff48c04dc18 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -128,6 +128,15 @@
  */
 #define PLAT_ARM_MAX_BL31_SIZE		0x1E000
 
+#if JUNO_AARCH32_EL3_RUNTIME
+/*
+ * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
+ * Payload. We also need to take care of SCP_BL2 size as well, as the SCP_BL2
+ * is loaded into the space BL32 -> BL1_RW_BASE
+ */
+# define PLAT_ARM_MAX_BL32_SIZE		0x1E000
+#endif
+
 /*
  * Since free SRAM space is scant, enable the ASSERTION message size
  * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40).
diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c
index 2771e0f3794d1b0c648ac03438f85eb8e741b5ea..cedef66c9a0a585135726ff3da0d8fb09677c8ed 100644
--- a/plat/arm/board/juno/juno_bl2_setup.c
+++ b/plat/arm/board/juno/juno_bl2_setup.c
@@ -29,33 +29,4 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
 
 	return err;
 }
-
-#if !CSS_USE_SCMI_SDS_DRIVER
-/*
- * We need to override some of the platform functions when booting SP_MIN
- * on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as
- * in case of SDS, the structures remain in memory and doesn't need to be
- * overwritten.
- */
-
-static unsigned int scp_boot_config;
-
-void bl2_early_platform_setup(meminfo_t *mem_layout)
-{
-	arm_bl2_early_platform_setup(mem_layout);
-
-	/* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */
-	VERBOSE("BL2: Saving SCP Boot config = 0x%x\n", scp_boot_config);
-	scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR);
-}
-
-void bl2_platform_setup(void)
-{
-	arm_bl2_platform_setup();
-
-	mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
-	VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config);
-}
-#endif
-
 #endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 5cd125bff07f9b2b391916f34468dc2403c66ba5..bfb7847fed016fd4e685c54d790c04d3b2566929 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -31,6 +31,19 @@ JUNO_AARCH32_EL3_RUNTIME	:=	0
 $(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME))
 $(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME))
 
+ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+# Include BL32 in FIP
+NEED_BL32		:= yes
+# BL31 is not required
+override BL31_SOURCES =
+
+# The BL32 needs to be built separately invoking the AARCH32 compiler and
+# be specifed via `BL32` build option.
+  ifneq (${ARCH}, aarch32)
+    override BL32_SOURCES =
+  endif
+endif
+
 ifeq (${ARCH},aarch64)
 BL1_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S		\
 				lib/cpus/aarch64/cortex_a57.S		\
diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c
index 9b4800e340b87753c0f229cbb87f7257b91b0102..b4aafd464ae303263f1674a6f93ffd6fc7f66c88 100644
--- a/plat/arm/css/common/css_bl2_setup.c
+++ b/plat/arm/css/common/css_bl2_setup.c
@@ -49,13 +49,13 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
 }
 
 #if !CSS_USE_SCMI_SDS_DRIVER
-# ifdef EL3_PAYLOAD_BASE
+# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME
 
 /*
  * We need to override some of the platform functions when booting an EL3
- * payload. These needs to be done only for SCPI/BOM SCP systems as
- * in case of SDS, the structures remain in memory and doesn't need to be
- * overwritten.
+ * payload or SP_MIN on Juno AArch32. This needs to be done only for
+ * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and
+ * don't need to be overwritten.
  */
 
 static unsigned int scp_boot_config;