diff --git a/fdts/stm32mp15-ssp-bl2.dtsi b/fdts/stm32mp15-ssp-bl2.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..107f6e21664bc853c3216965700d8193bfc6edde
--- /dev/null
+++ b/fdts/stm32mp15-ssp-bl2.dtsi
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved
+ */
+
+/ {
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+#if STM32MP_USB_PROGRAMMER
+	aliases {
+		/delete-property/ serial1;
+	};
+#endif
+
+	/delete-node/ cpu0_opp_table;
+
+	nvmem_layout@0 {
+	/delete-property/ nvmem-cells;
+	/delete-property/ nvmem-cell-names;
+
+	nvmem-cells = <&cfg0_otp>,
+		      <&part_number_otp>,
+		      <&monotonic_otp>,
+		      <&nand_otp>,
+		      <&uid_otp>,
+		      <&package_otp>,
+		      <&hw2_otp>,
+		      <&pkh_otp>,
+		      <&cfg2_otp>,
+		      <&ssp_otp>,
+		      <&chip_otp>,
+		      <&rma_otp>;
+
+	nvmem-cell-names = "cfg0_otp",
+			   "part_number_otp",
+			   "monotonic_otp",
+			   "nand_otp",
+			   "uid_otp",
+			   "package_otp",
+			   "hw2_otp",
+			   "pkh_otp",
+			   "cfg2_otp",
+			   "ssp_otp",
+			   "chip_otp",
+			   "rma_otp";
+	};
+
+	/delete-node/ psci;
+
+	soc {
+		efuse@5c005000 {
+			cfg2_otp: cfg2_otp@8 {
+				reg = <0x8 0x4>;
+			};
+
+			ssp_otp: ssp_otp@20 {
+				reg = <0x20 0x4>;
+			};
+
+			chip_otp: chip_otp@a0 {
+				reg = <0xa0 0x40>;
+			};
+
+			rma_otp: rma_otp@e0 {
+				reg = <0xe0 0x4>;
+			};
+		};
+
+		/delete-node/ timer@40006000;
+		/delete-node/ timer@44006000;
+		/delete-node/ pwr_mcu@50001014;
+		/delete-node/ cryp@54001000;
+		/delete-node/ rng@54003000;
+		/delete-node/ memory-controller@58002000;
+		/delete-node/ spi@58003000;
+		/delete-node/ sdmmc@58005000;
+		/delete-node/ sdmmc@58007000;
+		/delete-node/ ddr@5a003000;
+		/delete-node/ spi@5c001000;
+		/delete-node/ rtc@5c004000;
+		/delete-node/ etzpc@5c007000;
+		/delete-node/ stgen@5c008000;
+		/delete-node/ i2c@5c009000;
+		/delete-node/ tamp@5c00a000;
+#if STM32MP_USB_PROGRAMMER
+		/delete-node/ serial@4000e000;
+		/delete-node/ serial@4000f000;
+		/delete-node/ serial@40011000;
+		/delete-node/ serial@40018000;
+		/delete-node/ serial@40019000;
+		/delete-node/ serial@44003000;
+		/delete-node/ serial@5c000000;
+#endif
+#if STM32MP_UART_PROGRAMMER
+		/delete-node/ usb-otg@49000000;
+		/delete-node/ usbphyc@5a006000;
+#endif
+
+		pin-controller@50002000 {
+			/delete-node/ fmc-0;
+			/delete-node/ qspi-clk-0;
+			/delete-node/ qspi-bk1-0;
+			/delete-node/ qspi-bk2-0;
+			/delete-node/ rtc-out2-rmp-pins-0;
+			/delete-node/ sdmmc1-b4-0;
+			/delete-node/ sdmmc1-dir-0;
+			/delete-node/ sdmmc2-b4-0;
+			/delete-node/ sdmmc2-b4-1;
+			/delete-node/ sdmmc2-d47-0;
+#if STM32MP_USB_PROGRAMMER
+			/delete-node/ uart7-0;
+			/delete-node/ uart7-1;
+			/delete-node/ usart2-0;
+			/delete-node/ usart3-0;
+			/delete-node/ usart3-1;
+#endif
+#if STM32MP_UART_PROGRAMMER
+			/delete-node/ usbotg_hs-0;
+			/delete-node/ usbotg-fs-dp-dm-0;
+#endif
+		};
+	};
+};
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 17728005c77dc997f87eb2d0e1ba527b2a462346..8c9d3afb491641e7c8ef58dcce0638f286a06505 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -335,15 +335,278 @@ BOOT_API_MCIC_RETRAM_REGION_TO_HASH_IN_BYTES_TAMP_BCK_REG_IDX		23
 /* 'K' 'B' 'U' 'P' -.> 'PUBK' */
 #define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK             0x4B425550
 
+#if STM32MP_SSP
+/* 'V' 'O' 'R' 'P' -.> 'PROV' */
+#define BOOT_API_CTX_SSP_CMD_PROV_SECRET		0x564F5250
+/*
+ * Possible values of boot context field
+ * 'ssp_config_ptr_in->ssp_cmd' written by bootROM as Acknowledge
+ * of a request of SSP by FSBL.
+ */
+
+/* Written by bootROM on SSP error */
+#define BOOT_API_CTX_SSP_CMD_INVALID			0x00000000
+/*
+ * 'A' 'B' 'U' 'P' -.> 'PUBA' : ACK of ECIES_CHIP_PUBK calculation
+ * request by bootROM.
+ */
+#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK		0x41425550
+/*
+ * 'A' 'O' 'R' 'P' -.> 'PROA' : ACK of OEM Secret Provisioning request
+ * by bootROM.
+ */
+#define BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK		0x414F5250
+
+/*
+ * Constants required for SSP
+ */
+/* '.' 'P' 'S' 'S' -.> 'SSP.' */
+#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_NORMAL	0x2E505353
+/* 'L' 'P' 'S' 'S' -.> 'SSPL' */
+#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_LIVE		0x4C505353
+/* version 1 */
+#define BOOT_API_SSP_LICENSE_LAYOUT_VERSION_TO_MATCH	0x00000001
+/* 'P' 'P' 'S' 'S' -.> 'SSPP' */
+#define BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP		0x50505353
+/* IV AES on 128 bits = 16 bytes and KEY AES on 128 bits = 16 bytes */
+#define BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES	32
+/* version 1 */
+#define BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH	0x00000001
+/*
+ * Scalar in Elliptic curve cryptography is an integer (often a Prime)
+ * the number of bytes of this scalar is defined below.
+ */
+#define BOOT_API_SSP_SCALAR_SIZE_BYTES				32
+
+/*
+ * In Elliptic curve cryptography coordinates of points are 2D P
+ * (Px, Py) as concatenation of two scalars.
+ */
+#define BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES \
+	(2 * BOOT_API_SSP_SCALAR_SIZE_BYTES)
+
+/* In Elliptic curve cryptography Private Keys are scalars */
+#define BOOT_API_SSP_PRIVK_KEY_SIZE_BYTES \
+	BOOT_API_SSP_SCALAR_SIZE_BYTES
+
+/*
+ * In ECIES algorithm the Shared Secret (SS) is
+ * the x coordinate (Px) of a point P(Px,Py) obtained on reference
+ * chosen NIST-P256 Elliptic curve.
+ */
+#define BOOT_API_SSP_ECDH_SHARED_SECRET_SIZE_BYTES \
+	BOOT_API_SSP_SCALAR_SIZE_BYTES
+
+/*
+ * In Elliptic curve cryptography Public Keys are Points on chosen
+ * Elliptic curve P(x,y).
+ * Public Key is the x, y coordinates concatenated
+ * Ecies_eph_pubk and OEM_ECDSA_PUBK are each 64 bytes = 512 bits key
+ * sizes.
+ */
+#define BOOT_API_SSP_PUBK_KEY_SIZE_BYTES \
+	BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES
+
+/*
+ * Size in bytes of ECIES_Chip_pubk obtained from bootROM at end of SSP
+ * phase 1 : Chip public key calculation.
+ */
+#define BOOT_API_SSP_ECIES_CHIP_PUBK_SIZE_BYTES \
+	BOOT_API_SSP_PUBK_KEY_SIZE_BYTES
+
+/* AES-GCM authentication tag size is 16 bytes = 128 bits */
+#define BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES		16
+
+/* AES-GCM Symmetric Key size is 16 bytes = 128 bits */
+#define BOOT_API_SSP_AES_GCM_KEY_SIZE_BYTES			16
+
+/* AES-GCM Initialization Vector (IV) size is of 16 bytes = 128 bits */
+#define BOOT_API_SSP_AES_GCM_IV_SIZE_BYTES			16
+
+/*
+ * 88 bytes (license_type, live_session_id, license_version,
+ * fsbl_min_version, rfu[8], eph_ecies_pubk[])
+ */
+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE	88
+
+/*
+ * 32 bytes AAD License Secret from 2nd round KDF-SHA-256
+ * from ECDH Shared Secret hence KDF[32..63] aka "Authorization Token"
+ */
+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF	32
+
+/*
+ * Total License AAD size = 88 + 32 = 120 bytes
+ */
+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_SIZE_BYTES \
+	(BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE + \
+	 BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF)
+
+/*
+ * AAD for Payload size : composed of :
+ * payload_magic, payload_protocol_version, oem_ecdsa_pubk[], oem_secret_size
+ * = 4 + 4 + 64 + 4 = 76 bytes AAD for Payload
+ */
+#define BOOT_API_SSP_AES_GCM_PAYLOAD_AAD_SIZE_BYTES		76
+
+/*
+ * OEM Secrets max size in bytes :
+ * [OTP[95:59] + OTP_CFG56 (RMA Unlock and Relock passwords)] x 4 bytes
+ * by OTP word = 152 bytes
+ */
+#define BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES			152
+
+/*
+ * Possible values of boot context field 'ssp_status'
+ * as can be read by FSBL-SSP
+ */
+#define BOOT_API_CTX_SSP_STATUS_NO_SSP				0
+#define BOOT_API_CTX_SSP_STATUS_CHIP_PUBK_CALC_FINISHED		1
+#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FINISHED		2
+#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FORBIDDEN		3
+
+/*
+ * Reserved size for future use
+ */
+#define BOOT_API_SSP_HSM_OEM_RFU_SIZE				8
+
 /*
  * Exported types
  */
 
+/*
+ * SSP related definitions
+ */
+/*
+ * SSP BLOB License structure : Binary Large OBject License structure
+ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret
+ * provisioning.
+ * License information data, the structure is read by bootROM.
+ */
+typedef struct {
+	/*
+	 * License Type provided by HSM-OEM tool
+	 * should match Normal SSP License of Live SSP License.
+	 */
+	uint32_t license_type;
+
+	/* Live Session ID provided by HSM-OEM tool */
+	uint32_t live_session_id;
+
+	/*
+	 * Version of the License Protocol (Structure)
+	 * should be incremented each time a new.
+	 */
+	uint32_t license_version;
+
+	/*
+	 * Minimum FSBL version to be compared
+	 * with FSBL Header field 'imageVersion'.
+	 */
+	uint32_t fsbl_min_version;
+
+	/* RFU provided by HSM-OEM tool */
+	uint8_t  rfu[BOOT_API_SSP_HSM_OEM_RFU_SIZE];
+
+	/*
+	 * Ephemeral ECIES Public Key from HSM-OEM
+	 * 64 bytes = 512 bits.
+	 */
+	uint8_t  eph_ecies_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES];
+
+	/*
+	 * Encrypted (IV,Key) : with Shared Secret based on
+	 * 'Ephemeral ECIES Key pair' and 'ECIES Chip Key pair'.
+	 */
+	uint8_t encrypted_iv_and_key
+		[BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES];
+
+	/*
+	 * AUTH_TAG AES-GCM from encryption of (IV, Key)
+	 * in HSM-OEM with License AAD scheme
+	 * License Tag is 16 bytes = 128 bits.
+	 */
+	uint8_t  license_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES];
+
+} boot_api_ssp_blob_license_t;
+
+/*
+ * SSP BLOB Payload structure : Binary Large OBject Payload Structure
+ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret
+ * provisioning input data, the structure is read by bootROM
+ * The BLOB Payload size is fixed to a max size of 244 bytes based
+ * on a max number of bytes of OEM secret derived from OTP upper free
+ * area in STM32MP15xx cut 2.0.In this table oem_encrypted_secrets[]
+ * of max size only the first 'p_blob_payload->oem_secret_size_bytes'
+ * bytes will be considered and used by bootROM.
+ */
+typedef struct {
+	/*
+	 * BLOB Payload Magic : for memory validity check of BLOB Payload
+	 * to match against BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP by bootROM.
+	 */
+	uint32_t payload_magic;
+
+	/*
+	 * SSP Payload protocol version : on 32 bits
+	 * to be checked by bootROM for equality with
+	 * BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH
+	 * ie : 0x00000001 : version 1 of SSP Payload
+	 */
+	uint32_t payload_protocol_version;
+
+	/*
+	 * OEM_ECDSA_PUBK Public Key defined by OEM
+	 * 64 bytes = 512 bits
+	 */
+	uint8_t  oem_ecdsa_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES];
+
+	/*
+	 * Size of Table of OEM Secrets encrypted with AES-GCM (Key,IV) from
+	 * License field 'encrypted_iv_and_key[]'
+	 * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES:
+	 * is verified by bootROM.
+	 */
+	uint32_t oem_secret_size_bytes;
+
+	/*
+	 * AUTH_TAG AES-GCM computed by HSM-OEM when encrypting OEM Secrets with
+	 * (Key,IV) using special AAD scheme for Payload.
+	 * 16 bytes = 128 bits
+	 */
+	uint8_t  payload_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES];
+
+	/*
+	 * OEM Secrets encrypted with AES-GCM (IV, Key) from
+	 * License field 'encrypted_iv_and_key[]'.
+	 * The payload size is 'oem_secret_size_bytes'
+	 * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES =
+	 *  152 bytes : OEM Secrets max size in bytes :
+	 * [OTP_CFG56, OTP_CFG59, OTP_CFG60..95] x 4 bytes by OTP word.
+	 */
+	uint8_t oem_encrypted_secrets[BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES];
+
+} boot_api_ssp_blob_payload_t;
+#endif
+
 /* SSP Configuration structure */
 typedef struct {
 	/* SSP Command*/
 	uint32_t ssp_cmd;
+#if STM32MP_SSP
+	/* ECIES chip public key */
+	uint8_t *p_chip_pubk;
+	/* Blob License Address */
+	boot_api_ssp_blob_license_t *p_blob_license;
+	/* Blob Payload Address */
+	boot_api_ssp_blob_payload_t *p_blob_payload;
+	/* Secrets Decrypted Address */
+	uint8_t *p_ssp_oem_secrets_decrypted;
+	/* Reserved for Future Use (RFU) */
+	uint32_t padding_rfu;
+#else
 	uint8_t	reserved[20];
+#endif
 } boot_api_ssp_config_t;
 
 /*
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 3067420d31fb40c5145c328467c3e891247b37be..fba18b4de8dc48a88107cdabb0a7a724e66cb68a 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -38,6 +38,9 @@ STM32MP_DDR_DUAL_AXI_PORT:= 	1
 STM32_HEADER_VERSION_MAJOR:=	1
 STM32_HEADER_VERSION_MINOR:=	0
 
+# STM32 Secure Secret Provisioning mode (SSP)
+STM32MP_SSP		?=	0
+
 ifeq ($(AARCH32_SP),sp_min)
 # Disable Neon support: sp_min runtime may conflict with non-secure world
 TF_CFLAGS		+=	-mfloat-abi=soft
@@ -157,6 +160,7 @@ $(eval $(call assert_booleans,\
 		STM32MP_USB_PROGRAMMER \
 		STM32MP_USE_STM32IMAGE \
 		STM32MP_DDR_DUAL_AXI_PORT \
+		STM32MP_SSP \
 )))
 
 $(eval $(call assert_numerics,\
@@ -181,6 +185,7 @@ $(eval $(call add_defines,\
 		STM32_TF_VERSION \
 		STM32MP_USE_STM32IMAGE \
 		STM32MP_DDR_DUAL_AXI_PORT \
+		STM32MP_SSP \
 )))
 
 # Include paths and source files
@@ -347,6 +352,10 @@ BL2_SOURCES		+=	lib/optee/optee_utils.c
 BL2_SOURCES		+=	plat/st/stm32mp1/stm32mp1_critic_power.c
 BL2_SOURCES		+=	plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S
 
+ifeq ($(STM32MP_SSP),1)
+include plat/st/stm32mp1/stm32mp1_ssp.mk
+endif
+
 # Compilation rules
 .PHONY: check_dtc_version stm32image clean_stm32image check_boot_device
 .SUFFIXES:
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
index e75571f98afcb1dabe971f16e743502cab42b54c..273c1cf9d8ece52d705ba3a2380f72f90aa71f32 100644
--- a/plat/st/stm32mp1/services/bsec_svc.c
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -27,10 +27,6 @@
 
 #include "bsec_svc.h"
 
-#define SSP_OTP_REQ		BIT(BOOT_API_OTP_SSP_REQ_BIT_POS)
-#define SSP_OTP_SUCCESS		BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS)
-#define SSP_OTP_MASK		(SSP_OTP_REQ | SSP_OTP_SUCCESS)
-
 enum bsec_ssp_status {
 	BSEC_NO_SSP = 0,
 	BSEC_SSP_SET,
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index fc5c1183c9b9256092263c3dd81aea7a5df2a87d..b49a0f5b3e0c08ddaf897af5d172e1c74ce90063 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -130,6 +130,7 @@ enum ddr_type {
 					 (STM32MP_PARAM_LOAD_SIZE +	\
 					  STM32MP_HEADER_SIZE))
 
+#if !STM32MP_SSP
 #if STM32MP_USE_STM32IMAGE
 #define STM32MP_BL2_SIZE		U(0x0001C000)	/* 112 KB for BL2 */
 
@@ -173,6 +174,7 @@ enum ddr_type {
 #define STM32MP_BL32_SIZE		U(0x0001A000)	/* 100 KB for BL32 */
 #endif
 #endif /* STM32MP_USE_STM32IMAGE */
+#endif /* STM32MP_SSP */
 
 #if defined(IMAGE_BL2)
  #define STM32MP_DEFAULT_XLAT		U(2) /* 8 KB for mapping */
@@ -212,6 +214,29 @@ enum ddr_type {
   #endif
 #endif
 
+#if STM32MP_SSP
+#define STM32MP_BL2_DTB_SIZE		U(0x00004000)	/* 16 KB for DTB */
+
+#define STM32MP_BL2_DTB_BASE		(STM32MP_SYSRAM_BASE + \
+					 STM32MP_HEADER_RESERVED_SIZE)
+
+#define STM32MP_BL2_RO_SIZE		U(0x0000C000)	/* 48 Ko for BL2 */
+
+#define STM32MP_BL2_RO_BASE		STM32MP_BL2_DTB_BASE + \
+					STM32MP_BL2_DTB_SIZE
+
+#define STM32MP_BL2_RW_BASE		(STM32MP_BL2_RO_BASE + \
+					 STM32MP_BL2_RO_SIZE)
+
+#define STM32MP_BL2_RW_SIZE		(STM32MP_SYSRAM_BASE + \
+					 STM32MP_SYSRAM_SIZE - \
+					 STM32MP_BL2_RW_BASE)
+
+#define STM32MP_DTB_SIZE		STM32MP_BL2_DTB_SIZE
+#define STM32MP_DTB_BASE		STM32MP_BL2_DTB_BASE
+
+#define TF_A_MAPPING_START		STM32MP_BL2_DTB_BASE
+#else
 #if STM32MP_USE_STM32IMAGE
 /* DTB initialization value */
 #define STM32MP_DTB_SIZE		U(0x00006000)	/* 24 KB for DTB */
@@ -240,6 +265,7 @@ enum ddr_type {
 #endif
 #define TF_A_MAPPING_START		STM32MP_BL2_DTB_BASE
 #endif /* STM32MP_USE_STM32IMAGE */
+#endif /* STM32MP_SSP */
 
 #define STM32MP_FW_CONFIG_BASE		(STM32MP_SYSRAM_BASE + \
 					 STM32MP_SYSRAM_SIZE - \
@@ -429,11 +455,35 @@ enum ddr_type {
 #define UID_OTP				"uid_otp"
 #define PKH_OTP				"pkh_otp"
 #define BOARD_ID_OTP			"board_id"
+#define CFG2_OTP			"cfg2_otp"
+#define SSP_OTP				"ssp_otp"
+#define CHIP_CERTIFICATE_OTP		"chip_otp"
+#define RMA_OTP				"rma_otp"
 
 /* OTP mask */
 /* CFG0 */
 #define CFG0_CLOSED_DEVICE		BIT(6)
 
+/* CFG2 */
+#define OTP_CFG2_SEC_COUNTER_MASK	GENMASK_32(27, 20)
+#define OTP_CFG2_SEC_COUNTER_SHIFT	U(20)
+#define OTP_CFG2_ST_KEY_MASK		GENMASK_32(31, 28)
+#define OTP_CFG2_ST_KEY_SHIFT		U(28)
+
+/* SSP */
+#define SSP_OTP_REQ			BIT(BOOT_API_OTP_SSP_REQ_BIT_POS)
+#define SSP_OTP_SUCCESS			BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS)
+#define SSP_OTP_MASK			GENMASK_32(BOOT_API_OTP_SSP_SUCCESS_BIT_POS, \
+						   BOOT_API_OTP_SSP_REQ_BIT_POS)
+#define SSP_OTP_SECRET_BASE		U(59)
+#define SSP_OTP_SECRET_END		U(95)
+
+/* CHIP_CERT */
+#define CHIP_CERTIFICATE_MAX_SIZE	U(0x40)
+
+/* RMA */
+#define RMA_OTP_MASK			GENMASK_32(29, 0)
+
 /* PART NUMBER */
 #define PART_NUMBER_OTP_PART_MASK	GENMASK_32(7, 0)
 #define PART_NUMBER_OTP_PART_SHIFT	0
diff --git a/plat/st/stm32mp1/stm32mp1_ssp.c b/plat/st/stm32mp1/stm32mp1_ssp.c
new file mode 100644
index 0000000000000000000000000000000000000000..bcbf374782a75a63ee57114e4a2cc0d84fced3e2
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_ssp.c
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <endian.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32_console.h>
+#include <drivers/st/stm32_hash.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32_uart.h>
+#include <drivers/st/stm32mp_pmic.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <drivers/st/stpmic1.h>
+#include <lib/mmio.h>
+#include <lib/usb/usb_core.h>
+#include <lib/usb/usb_st_dfu.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <stm32cubeprogrammer.h>
+
+#define CERT_CHIP_ID_LEN		U(3)
+#define CERT_SECURITY_COUNTER_LEN	U(2)
+#define CERT_SECURITY_COUNTER_SHIFT	CERT_CHIP_ID_LEN
+#define CERT_RFU_LEN			U(1)
+#define CERT_RFU_SHIFT			(CERT_SECURITY_COUNTER_LEN + \
+					 CERT_SECURITY_COUNTER_SHIFT)
+#define CERT_PRODUCT_KEY_LEN		U(2)
+#define CERT_PRODUCT_KEY_SHIFT		(CERT_RFU_LEN + CERT_RFU_SHIFT)
+#define CERT_PRODUCT_ID_SIZE		(CERT_PRODUCT_KEY_LEN + \
+					 CERT_PRODUCT_KEY_SHIFT)
+#define CERT_SIGNATURE_LEN		CHIP_CERTIFICATE_MAX_SIZE
+#define CERT_SIGNATURE_SHIFT		(CERT_PRODUCT_ID_SIZE + \
+					 BOOT_API_SSP_PUBK_KEY_SIZE_BYTES)
+#define CERTIFICATE_SIZE		(CERT_PRODUCT_ID_SIZE + \
+					 BOOT_API_SSP_PUBK_KEY_SIZE_BYTES + \
+					 CERT_SIGNATURE_LEN) /* 136 bytes */
+#define RESET_TIMEOUT_US_1MS		U(1000)
+#define BLOB_FILE_MAX_ADDR		BL2_RW_LIMIT
+
+/* Local status for SSP processing sequences */
+typedef enum {
+	SSP_NONE,
+	SSP_GET_CERT,
+	SSP_FLASH_OEM,
+	SSP_DONE,
+	SSP_ERROR
+} ssp_result_e;
+
+struct otp_val {
+	uint32_t idx;
+	uint32_t nb;
+};
+
+static struct otp_val otp_ssp;
+static struct otp_val otp_rma;
+static struct otp_val otp_pubkey;
+
+#if DEBUG
+static console_t console;
+#endif
+
+/* Platform empty definition required */
+void bl2_platform_setup(void) {}
+struct bl_params *plat_get_next_bl_params(void) { return NULL; }
+void plat_flush_next_bl_params(void) {}
+struct bl_load_info *plat_get_bl_image_load_info(void) { return NULL; }
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	return 0;
+}
+
+/*
+ * Initialized OTP index from device tree.
+ */
+static int initialize_otp(void)
+{
+	uint32_t len;
+
+	/* OTP SSP */
+	if (stm32_get_otp_index(SSP_OTP, &otp_ssp.idx, NULL) != 0) {
+		VERBOSE("%s: get index error\n", __func__);
+		return -EINVAL;
+	}
+
+	/* OTP public key */
+	if (stm32_get_otp_index(PKH_OTP, &otp_pubkey.idx, &len) != 0) {
+		VERBOSE("%s: get index error\n", __func__);
+		return -EINVAL;
+	}
+
+	if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) {
+		VERBOSE("%s: length Error\n", __func__);
+		return -EINVAL;
+	}
+
+	otp_pubkey.nb = len / __WORD_BIT;
+
+	/* OTP RMA */
+	if (stm32_get_otp_index(RMA_OTP, &otp_rma.idx, NULL) != 0) {
+		VERBOSE("%s: get index error\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Compute HASH from public key and burn it in OTP.
+ */
+static int ssp_pub_key_prog(boot_api_context_t *boot_context)
+{
+	uint8_t key_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES] __aligned(4);
+	uint8_t *pubk = (uint8_t *)
+		boot_context->p_ssp_config->p_blob_payload->oem_ecdsa_pubk;
+	uint32_t *value = (uint32_t *)key_hash;
+	uint32_t i;
+
+	if (stm32_hash_register() != 0) {
+		return -EINVAL;
+	}
+
+	stm32_hash_init(HASH_SHA256);
+
+	if (stm32_hash_final_update(pubk, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES,
+				    key_hash) != 0) {
+		ERROR("Hash of payload failed\n");
+		return -EINVAL;
+	}
+
+	for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) {
+		if (bsec_program_otp(bswap32(*value), i) != BSEC_OK) {
+			return -EINVAL;
+		}
+
+		value++;
+		if (bsec_permanent_lock_otp(i) != BSEC_OK) {
+			ERROR("Error locking OTP %i\n", i);
+			panic();
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Burn OTP to close device.
+ */
+static int ssp_close_device(void)
+{
+	uint32_t otp;
+	uint32_t value;
+
+	if (stm32_get_otp_index(CFG0_OTP, &otp, NULL) != 0) {
+		return -EINVAL;
+	}
+
+	if (bsec_read_otp(&value, otp) != BSEC_OK) {
+		return -EINVAL;
+	}
+
+	if ((value & CFG0_CLOSED_DEVICE) != 0U) {
+		ERROR("Device already closed\n");
+		return -EINVAL;
+	}
+
+	value |= CFG0_CLOSED_DEVICE;
+	if (bsec_program_otp(value, otp) != BSEC_OK) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * OTP initial check to detect previous values.
+ */
+static int ssp_secrets_check(boot_api_context_t *boot_ctx)
+{
+	uint32_t i;
+	uint32_t check_val;
+	uint32_t otp_bytes = boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes;
+	uint32_t otp_decrypted;
+
+	if (otp_bytes == 0U) {
+		return -EINVAL;
+	}
+
+	for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) {
+		if (stm32_get_otp_value_from_idx(i, &check_val) != 0) {
+			return -EINVAL;
+		}
+
+		if (check_val != 0U) {
+			ERROR("OTP %u value already programmed\n", i);
+			return -EINVAL;
+		}
+	}
+
+	otp_decrypted = round_up(otp_bytes, sizeof(uint32_t)) / sizeof(uint32_t);
+
+	/* OTP decrypted include RMA password */
+	if (otp_decrypted > (2U + SSP_OTP_SECRET_END - SSP_OTP_SECRET_BASE)) {
+		return -EINVAL;
+	}
+
+	/* Check RMA password */
+	if (stm32_get_otp_value_from_idx(otp_rma.idx, &check_val) != 0) {
+		return -EINVAL;
+	}
+
+	if (check_val != 0U) {
+		ERROR("OTP %s value already programmed\n", RMA_OTP);
+		return -EINVAL;
+	}
+
+	/* Check all OTP available */
+	for (i = SSP_OTP_SECRET_BASE; i < SSP_OTP_SECRET_BASE + otp_decrypted - 1U; i++) {
+		if (stm32_get_otp_value_from_idx(i, &check_val) != 0) {
+			return -EINVAL;
+		}
+
+		if (check_val != 0U) {
+			ERROR("OTP %u value already programmed\n", i);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Burn OTP with the decrypted secret received.
+ */
+static int ssp_secrets_flash(boot_api_context_t *boot_ctx)
+{
+	uint32_t i;
+	uint32_t *val;
+	uint32_t otp_bytes =
+		boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes;
+	uint32_t otp_decrypted;
+	uint32_t otp_mask = 0U;
+
+	if (otp_bytes == 0U) {
+		return -EINVAL;
+	}
+
+	if (otp_bytes % sizeof(uint32_t) != 0U) {
+		otp_mask = GENMASK_32(((otp_bytes % sizeof(uint32_t)) *
+				       sizeof(uint32_t)) - 1, 0);
+	}
+
+	val = (uint32_t *)boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted;
+
+	otp_decrypted = round_up(otp_bytes, sizeof(uint32_t)) / sizeof(uint32_t);
+
+	/* Burn RMA password */
+	if (bsec_program_otp((*val & RMA_OTP_MASK), otp_rma.idx) !=  BSEC_OK) {
+		WARN("RMA programing failed\n");
+		return -EINVAL;
+	}
+
+	val++;
+	otp_decrypted--;
+	for (i = SSP_OTP_SECRET_BASE; i < (SSP_OTP_SECRET_BASE + otp_decrypted - 1U); i++) {
+		if (*val == 0U) {
+			val++;
+			continue;
+		}
+
+		if (bsec_program_otp(*val, i) != BSEC_OK) {
+			WARN("Error writing OTP %i\n", i);
+			return -EINVAL;
+		}
+
+		if (bsec_permanent_lock_otp(i) != BSEC_OK) {
+			WARN("Error locking OTP %i\n", i);
+			return -EINVAL;
+		}
+
+		val++;
+	}
+
+	if (*val == 0U) {
+		return 0;
+	}
+
+	/* Mask the last OTP value if needed */
+	if (otp_mask != 0U) {
+		*val &= otp_mask;
+	}
+
+	if (bsec_program_otp(*val, i) != BSEC_OK) {
+		WARN("Error writing OTP %i\n", i);
+		return -EINVAL;
+	}
+
+	if (bsec_permanent_lock_otp(i) != BSEC_OK) {
+		WARN("Error locking OTP %i\n", i);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Finish SSP processing by fusing OTP SSP success.
+ */
+static int ssp_finish_process(void)
+{
+	uint32_t val;
+
+	if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) {
+		return -EINVAL;
+	}
+
+	if ((val & SSP_OTP_SUCCESS) != 0U) {
+		WARN("Error while configuring OTP\n");
+		return -EINVAL;
+	}
+
+	val |= SSP_OTP_SUCCESS;
+	if (bsec_program_otp(val, otp_ssp.idx) != BSEC_OK) {
+		return -EINVAL;
+	}
+
+	VERBOSE("Write OTP Success\n");
+
+	return 0;
+}
+
+/*
+ * Transform integer to string.
+ */
+static void itoa(uint32_t num, char *str, int nb)
+{
+	if (num == 0U) {
+		while (nb-- != 0U) {
+			str[nb] = '0';
+		}
+
+		return;
+	}
+
+	while (num != 0U) {
+		int rem = num % 16;
+
+		str[--nb] = (rem > 9) ? (rem - 10) + 'A' : rem + '0';
+		num /= 16;
+	}
+
+	while (nb != 0) {
+		str[--nb] = '0';
+	}
+}
+
+/*
+ * Return chip product ID.
+ */
+static int ssp_get_product_id(char *msg)
+{
+	uint32_t otp;
+	uint32_t otp_idx;
+	uint32_t chip_id;
+
+	if (stm32_get_otp_index(CFG2_OTP, &otp_idx, NULL) != 0) {
+		VERBOSE("Get index error\n");
+		return -EINVAL;
+	}
+
+	if (stm32_get_otp_value_from_idx(otp_idx, &otp) != 0) {
+		return -EINVAL;
+	}
+
+	if (stm32mp1_dbgmcu_get_chip_dev_id(&chip_id) < 0) {
+		return -EINVAL;
+	}
+
+	itoa(chip_id, msg, CERT_CHIP_ID_LEN);
+	itoa((otp & OTP_CFG2_SEC_COUNTER_MASK) >> OTP_CFG2_SEC_COUNTER_SHIFT,
+	     msg + CERT_SECURITY_COUNTER_SHIFT,
+	     CERT_SECURITY_COUNTER_LEN);
+
+	itoa(0, msg + CERT_RFU_SHIFT, CERT_RFU_LEN);
+	itoa((otp & OTP_CFG2_ST_KEY_MASK) >> OTP_CFG2_ST_KEY_SHIFT,
+	     msg + CERT_PRODUCT_KEY_SHIFT,
+	     CERT_PRODUCT_KEY_LEN);
+
+	return 0;
+}
+
+/*
+ * Construct SSP certificate.
+ */
+static int prepare_certificate(uint8_t *cert, const uint8_t *pubkey)
+{
+	uint32_t i;
+	uint32_t j;
+	uint32_t otp;
+	uint32_t otp_idx;
+	uint32_t otp_len;
+
+	/* Prepare the ROM Security constant */
+	if (ssp_get_product_id((char *)cert) != 0) {
+		return -EINVAL;
+	}
+
+	/* Prepare public key and certificate for flashloader */
+	/* Read Public Key from boot_context */
+	memcpy(cert + CERT_PRODUCT_ID_SIZE, pubkey, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES);
+
+	if (stm32_get_otp_index(CHIP_CERTIFICATE_OTP,
+				&otp_idx, &otp_len) != 0) {
+		VERBOSE("Get index error\n");
+		return -EINVAL;
+	}
+
+	if (otp_len != (CHAR_BIT * CHIP_CERTIFICATE_MAX_SIZE)) {
+		VERBOSE("Length error\n");
+		return -EINVAL;
+	}
+
+	otp_len /= __WORD_BIT;
+
+	/* Read Certificat from OTP */
+	for (i = otp_idx, j = 0U; i < (otp_idx + otp_len); i++, j++) {
+		uint32_t otp_s;
+
+		if (stm32_get_otp_value_from_idx(i, &otp) != 0) {
+			return -EINVAL;
+		}
+
+		otp_s = bswap32(otp);
+		memcpy(&cert[CERT_SIGNATURE_SHIFT + (sizeof(uint32_t) * j)],
+		       &otp_s, sizeof(uint32_t));
+	}
+
+	return 0;
+}
+
+/*
+ * Clean external data and bootrom context secret values.
+ */
+static void ssp_cleanup(boot_api_context_t *boot_context)
+{
+	boot_api_ssp_config_t *ssp_config = boot_context->p_ssp_config;
+
+	/* Cleanup boot_context */
+	if (ssp_config->p_ssp_oem_secrets_decrypted != NULL) {
+		zeromem(ssp_config->p_ssp_oem_secrets_decrypted,
+			BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES);
+#ifndef DCACHE_OFF
+		flush_dcache_range((uintptr_t)ssp_config->p_ssp_oem_secrets_decrypted,
+				   BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES);
+#endif
+		ssp_config->p_ssp_oem_secrets_decrypted = NULL;
+	}
+
+	if (ssp_config->p_chip_pubk != NULL) {
+		zeromem(ssp_config->p_chip_pubk,
+			BOOT_API_SSP_PUBK_KEY_SIZE_BYTES);
+#ifndef DCACHE_OFF
+		flush_dcache_range((uintptr_t)ssp_config->p_chip_pubk,
+				   BOOT_API_SSP_PUBK_KEY_SIZE_BYTES);
+#endif
+		ssp_config->p_chip_pubk = NULL;
+	}
+
+	if (ssp_config->p_blob_license != NULL) {
+		zeromem(ssp_config->p_blob_license,
+			sizeof(boot_api_ssp_blob_license_t));
+#ifndef DCACHE_OFF
+		flush_dcache_range((uintptr_t)ssp_config->p_blob_license,
+				   sizeof(boot_api_ssp_blob_license_t));
+#endif
+		ssp_config->p_blob_license = NULL;
+	}
+
+	if (ssp_config->p_blob_payload != NULL) {
+		zeromem(ssp_config->p_blob_payload,
+			sizeof(boot_api_ssp_blob_payload_t));
+#ifndef DCACHE_OFF
+		flush_dcache_range((uintptr_t)ssp_config->p_blob_payload,
+			   sizeof(boot_api_ssp_blob_payload_t));
+#endif
+		ssp_config->p_blob_payload = NULL;
+	}
+
+	ssp_config->ssp_cmd = 0U;
+
+#ifndef DCACHE_OFF
+	flush_dcache_range((uintptr_t)boot_context->p_ssp_config,
+			   sizeof(boot_api_ssp_config_t));
+#endif
+}
+
+/*
+ * Send certificate to the programmer and retrieve the associated
+ * encrypted file.
+ */
+static int ssp_download_phase(boot_api_context_t *boot_ctx)
+{
+	uint8_t *blob_file;
+#if STM32MP_USB_PROGRAMMER
+	usb_handle_t *pdev;
+#endif
+#if STM32MP_UART_PROGRAMMER
+	uintptr_t uart_base;
+#endif
+	int result = 0;
+	uint8_t cert[CERTIFICATE_SIZE];
+
+	blob_file = (uint8_t *)page_align(BLOB_FILE_MAX_ADDR -
+					  sizeof(boot_api_ssp_blob_license_t) -
+					  sizeof(boot_api_ssp_blob_payload_t),
+					  DOWN);
+
+	if (prepare_certificate(cert, boot_ctx->p_ssp_config->p_chip_pubk) != 0) {
+		return -EINVAL;
+	}
+
+	switch (boot_ctx->boot_interface_selected) {
+#if STM32MP_USB_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+
+		/* init USB on platform */
+		pdev = usb_dfu_plat_init();
+
+		result = stm32cubeprog_usb_ssp(pdev, (uintptr_t)cert,
+					       sizeof(cert), (uintptr_t)blob_file,
+					       sizeof(boot_api_ssp_blob_license_t) +
+					       sizeof(boot_api_ssp_blob_payload_t));
+		if (result != 0) {
+			return -EINVAL;
+		}
+
+		break;
+#endif
+
+#if STM32MP_UART_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+		uart_base = get_uart_address(boot_ctx->boot_interface_instance);
+
+		if (uart_base == 0U) {
+			return -EINVAL;
+		}
+
+		result = stm32cubeprog_uart_ssp(uart_base, (uintptr_t)cert, sizeof(cert),
+						(uintptr_t)blob_file,
+						sizeof(boot_api_ssp_blob_license_t) +
+						sizeof(boot_api_ssp_blob_payload_t));
+		if (result != 0) {
+			return -EINVAL;
+		}
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	boot_ctx->p_ssp_config->p_blob_license =
+		(boot_api_ssp_blob_license_t *)blob_file;
+
+	/* Payload is concatened with license file */
+	boot_ctx->p_ssp_config->p_blob_payload =
+		(boot_api_ssp_blob_payload_t *)(blob_file +
+		sizeof(boot_api_ssp_blob_license_t));
+
+#ifndef DCACHE_OFF
+	flush_dcache_range((uintptr_t)blob_file,
+			   sizeof(boot_api_ssp_blob_license_t) +
+			   sizeof(boot_api_ssp_blob_payload_t));
+#endif
+
+	/* Set return address for decrypted_secrets */
+	boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted =
+		boot_ctx->p_ssp_config->p_blob_payload->oem_encrypted_secrets;
+
+	return result;
+}
+
+/*
+ * Burn decrypted secrets into OTP, clean memory and close the device.
+ */
+static int ssp_secret_programming(boot_api_context_t *boot_context)
+{
+	int result;
+
+	result = ssp_secrets_check(boot_context);
+	if (result != 0) {
+		ERROR("SSP ERROR checking OTP\n");
+		goto clean;
+	}
+
+	result = ssp_pub_key_prog(boot_context);
+	if (result != 0) {
+		ERROR("SSP ERROR writing HASH key\n");
+		goto clean;
+	}
+
+	result = ssp_close_device();
+	if (result != 0) {
+		ERROR("SSP close device failed\n");
+		goto clean;
+	}
+
+	result = ssp_secrets_flash(boot_context);
+	if (result != 0) {
+		ERROR("SSP Secret flash failed\n");
+	}
+
+clean:
+	ssp_cleanup(boot_context);
+
+	if (result != 0) {
+		return result;
+	}
+
+	return ssp_finish_process();
+}
+
+/*
+ * Enable the SSP processing.
+ */
+static int ssp_enable_processing(boot_api_context_t *boot_context)
+{
+	uint32_t val;
+	int result;
+#if STM32MP_USB_PROGRAMMER
+	usb_handle_t *pdev;
+#endif
+#if STM32MP_UART_PROGRAMMER
+	uintptr_t uart_base;
+#endif
+
+	if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) {
+		return -EINVAL;
+	}
+
+	if (((val & SSP_OTP_MASK) == SSP_OTP_MASK) ||
+	    ((val & SSP_OTP_MASK) == SSP_OTP_SUCCESS)) {
+		return -EINVAL;
+	}
+
+	if ((val & SSP_OTP_MASK) == 0U) {
+		if (bsec_program_otp(SSP_OTP_REQ, otp_ssp.idx) != BSEC_OK) {
+			return -EINVAL;
+		}
+	}
+
+	switch (boot_context->boot_interface_selected) {
+#if STM32MP_USB_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+		/* init USB on platform */
+		pdev = usb_dfu_plat_init();
+
+		result = stm32cubeprog_usb_ssp(pdev, (uintptr_t)-1, 0,
+					       (uintptr_t)NULL, 0);
+		if (result != 0) {
+			return -EINVAL;
+		}
+
+		break;
+#endif
+
+#if STM32MP_UART_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+		uart_base = get_uart_address(boot_context->boot_interface_instance);
+		if (uart_base == 0U) {
+			return -EINVAL;
+		}
+
+		result = stm32cubeprog_uart_ssp(uart_base, (uintptr_t)-1, 0,
+						(uintptr_t)NULL, 0);
+		if (result != 0) {
+			return -EINVAL;
+		}
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	boot_context->p_ssp_config->ssp_cmd =
+		BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK;
+
+	return 0;
+}
+
+/*
+ * Retrieve the current status of the SSP from bootrom context and OTP value.
+ */
+static ssp_result_e ssp_check_status(boot_api_context_t *boot_context)
+{
+	uint32_t otp;
+
+	if (initialize_otp() < 0) {
+		return SSP_ERROR;
+	}
+
+	if (stm32_get_otp_value_from_idx(otp_ssp.idx, &otp) != 0) {
+		return SSP_ERROR;
+	}
+
+	if ((otp & SSP_OTP_REQ) == 0U) {
+		return SSP_NONE;
+	}
+
+	if ((otp & SSP_OTP_SUCCESS) != 0U) {
+		return SSP_DONE;
+	}
+
+	VERBOSE("Start Get ssp_cmd : %x\n",
+		boot_context->p_ssp_config->ssp_cmd);
+
+	switch (boot_context->p_ssp_config->ssp_cmd) {
+	case BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK:
+		INFO("Detected start SSP Phase 2\n");
+		return SSP_GET_CERT;
+	case BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK:
+		INFO("Detected start SSP Phase 3\n");
+		return SSP_FLASH_OEM;
+	default:
+		return SSP_NONE;
+	}
+}
+
+/*
+ * Start the SSP processing.
+ */
+static void ssp_start(boot_api_context_t *boot_context)
+{
+	int result;
+	uint8_t ssp_phase = ssp_check_status(boot_context);
+
+	switch (ssp_phase) {
+	case SSP_GET_CERT:
+		result = ssp_download_phase(boot_context);
+		if (result != 0) {
+			/*
+			 * Download Phase failed, clean, reset
+			 */
+			ssp_cleanup(boot_context);
+
+			ERROR("SSP_Error: Resetting target\n");
+		} else {
+			/* Process completed, go to Phase 3 */
+			boot_context->p_ssp_config->ssp_cmd =
+				BOOT_API_CTX_SSP_CMD_PROV_SECRET;
+		}
+
+		break;
+
+	case SSP_FLASH_OEM:
+		result = ssp_secret_programming(boot_context);
+		if (result != 0) {
+			ERROR("Error during provisionning\n");
+		} else {
+			NOTICE("Provisioning completed\n");
+		}
+
+		break;
+
+	case SSP_ERROR:
+		/*
+		 * Error during bootrom SSP processing
+		 */
+		result = -EINVAL;
+		ERROR("SSP_Error: Resetting target\n");
+		break;
+
+	case SSP_NONE:
+	default:
+		result = ssp_enable_processing(boot_context);
+		if (result != 0) {
+			ERROR("Start SSP Failed (%i)\n", result);
+		}
+	}
+
+	if ((result != 0) || (ssp_phase == SSP_FLASH_OEM)) {
+		goto out;
+	}
+
+	/*
+	 * Keep VDDCORE && VDD enabled if pmic used to generate
+	 * the required MPSYSRST.
+	 */
+	if (dt_pmic_status() > 0) {
+		const char *name;
+
+		name = stm32mp_get_cpu_supply_name();
+		if (name == NULL) {
+			goto out;
+		}
+
+		if (stpmic1_regulator_mask_reset_set(name) != 0) {
+			WARN("Failed to write %s reset mask\n", name);
+		}
+
+		name = stm32mp_get_vdd_supply_name();
+		if (name == NULL) {
+			goto out;
+		}
+
+		if (stpmic1_regulator_mask_reset_set(name) != 0) {
+			WARN("Failed to write %s reset mask\n", name);
+		}
+	} else {
+		static const char debug_msg[] = {
+			"SSP next step will be only guarantee if the VDD\n"
+			"domain is maintained during system reset\n"
+		};
+
+		NOTICE("%s", debug_msg);
+	}
+
+out:
+#ifndef DCACHE_OFF
+	if (boot_context->p_ssp_config != NULL) {
+		flush_dcache_range((uintptr_t)boot_context->p_ssp_config,
+				   sizeof(boot_api_ssp_config_t));
+	}
+#endif
+
+	stm32mp_system_reset();
+}
+
+#if DEBUG
+static void reset_uart(uint32_t reset)
+{
+	int ret;
+
+	ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS);
+	if (ret != 0) {
+		panic();
+	}
+
+	udelay(2);
+
+	ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS);
+	if (ret != 0) {
+		panic();
+	}
+
+	mdelay(1);
+}
+#endif
+
+void bl2_el3_early_platform_setup(u_register_t arg0,
+				  u_register_t arg1 __unused,
+				  u_register_t arg2 __unused,
+				  u_register_t arg3 __unused)
+{
+	stm32mp_save_boot_ctx_address(arg0);
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+#if DEBUG
+	int32_t result;
+	struct dt_node_info dt_uart_info;
+	const char *board_model;
+	uint32_t clk_rate;
+#endif
+	uintptr_t pwr_base;
+	uintptr_t rcc_base;
+
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
+	bool serial_uart_interface __unused =
+				(boot_context->boot_interface_selected ==
+				 BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART);
+	uintptr_t uart_prog_addr __unused;
+
+	if (bsec_probe() != 0) {
+		panic();
+	}
+
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+			BL_CODE_END - BL_CODE_BASE,
+			MT_CODE | MT_SECURE);
+
+#if SEPARATE_CODE_AND_RODATA
+	mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+			BL_RO_DATA_END - BL_RO_DATA_BASE,
+			MT_RO_DATA | MT_SECURE);
+#endif
+
+	/* Prevent corruption of preloaded Device Tree */
+	mmap_add_region(DTB_BASE, DTB_BASE,
+			DTB_LIMIT - DTB_BASE,
+			MT_RO_DATA | MT_SECURE);
+
+	configure_mmu();
+
+	if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
+		panic();
+	}
+
+	pwr_base = stm32mp_pwr_base();
+	rcc_base = stm32mp_rcc_base();
+
+	/*
+	 * Disable the backup domain write protection.
+	 * The protection is enable at each reset by hardware
+	 * and must be disabled by software.
+	 */
+	mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
+
+	while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
+		;
+	}
+
+	/* Reset backup domain on cold boot cases */
+	if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
+		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+
+		while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
+		       0U) {
+			;
+		}
+
+		mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+	}
+
+
+	generic_delay_timer_init();
+
+#if STM32MP_UART_PROGRAMMER
+	uart_prog_addr = get_uart_address(boot_context->boot_interface_instance);
+
+	/* Disable programmer UART before changing clock tree */
+	if (serial_uart_interface) {
+		stm32_uart_stop(uart_prog_addr);
+	}
+#endif
+
+	if (stm32mp1_clk_probe() < 0) {
+		panic();
+	}
+
+	if (dt_pmic_status() > 0) {
+		initialize_pmic();
+	}
+
+#if DEBUG
+	result = dt_get_stdout_uart_info(&dt_uart_info);
+
+	if ((result <= 0) ||
+	    (dt_uart_info.status == DT_DISABLED) ||
+#if STM32MP_UART_PROGRAMMER
+	    (serial_uart_interface &&
+	     (uart_prog_addr == dt_uart_info.base)) ||
+#endif
+	    (dt_uart_info.clock < 0) ||
+	    (dt_uart_info.reset < 0)) {
+		goto skip_console_init;
+	}
+
+	if (dt_set_stdout_pinctrl() != 0) {
+		goto skip_console_init;
+	}
+
+	if (dt_uart_info.status == DT_DISABLED) {
+		panic();
+	}
+
+	clk_enable((unsigned long)dt_uart_info.clock);
+
+	reset_uart((uint32_t)dt_uart_info.reset);
+
+	clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock);
+
+	if (console_stm32_register(dt_uart_info.base, clk_rate,
+				   STM32MP_UART_BAUDRATE, &console) == 0) {
+		panic();
+	}
+
+	console_set_scope(&console, CONSOLE_FLAG_BOOT |
+			  CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF);
+
+	stm32mp_print_cpuinfo();
+
+	board_model = dt_get_board_model();
+	if (board_model != NULL) {
+		NOTICE("Model: %s\n", board_model);
+	}
+
+	if ((boot_context->p_ssp_config == NULL) ||
+	    (boot_context->p_ssp_config->ssp_cmd !=
+	     BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK)) {
+		stm32mp_print_cpuinfo();
+		if (!stm32mp_is_auth_supported()) {
+			ERROR("Chip doesn't support SSP\n");
+			panic();
+		}
+	}
+
+skip_console_init:
+#endif
+	if (stm32mp_is_closed_device()) {
+		/* Closed chip required authentication */
+		ERROR("SSP not supported on closed chip\n");
+		panic();
+	}
+
+	if (stm32_iwdg_init() < 0) {
+		panic();
+	}
+
+	stm32_iwdg_refresh();
+
+	if (dt_pmic_status() > 0) {
+		initialize_pmic();
+		print_pmic_info_and_debug();
+	}
+
+	ssp_start(boot_context);
+
+	/* This must not be reached */
+	panic();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_ssp.mk b/plat/st/stm32mp1/stm32mp1_ssp.mk
new file mode 100644
index 0000000000000000000000000000000000000000..9041e6a0324bd4b14d4a82cc9fedd9d72fe7a510
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_ssp.mk
@@ -0,0 +1,84 @@
+#
+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ST_VERSION 		:=	r1.0-ssp
+VERSION_STRING		:=	v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING}
+
+# Required to use BL2_IN_XIP_MEM
+BL2_IN_XIP_MEM 		:= 	1
+
+SEPARATE_CODE_AND_RODATA :=	1
+
+TRUSTED_BOARD_BOOT	:=	0
+
+# Macros and rules to build TF-A binary
+STM32_TF_STM32		:=	$(addprefix ${BUILD_PLAT}/tf-a-ssp-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
+
+PLAT_BL_COMMON_SOURCES	:=	common/fdt_wrappers.c					\
+				plat/st/common/stm32mp_common.c				\
+				plat/st/stm32mp1/stm32mp1_private.c
+
+PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
+
+PLAT_BL_COMMON_SOURCES	+=	lib/cpus/aarch32/cortex_a7.S
+
+PLAT_BL_COMMON_SOURCES	+=	drivers/st/uart/aarch32/stm32_console.S
+
+PLAT_BL_COMMON_SOURCES	+=	drivers/arm/tzc/tzc400.c				\
+				drivers/clk/clk.c					\
+				drivers/delay_timer/delay_timer.c			\
+				drivers/delay_timer/generic_delay_timer.c		\
+				drivers/st/bsec/bsec2.c					\
+				drivers/st/clk/stm32mp_clkfunc.c			\
+				drivers/st/gpio/stm32_gpio.c				\
+				drivers/st/i2c/stm32_i2c.c				\
+				drivers/st/iwdg/stm32_iwdg.c				\
+				drivers/st/pmic/stm32mp_pmic.c				\
+				drivers/st/pmic/stpmic1.c				\
+				drivers/st/regulator/stm32mp_dummy_regulator.c		\
+				drivers/st/regulator/stm32mp_regulator.c		\
+				drivers/st/reset/stm32mp1_reset.c			\
+				plat/st/common/stm32mp_dt.c				\
+				plat/st/common/stm32mp_shres_helpers.c			\
+				plat/st/stm32mp1/stm32mp1_dbgmcu.c			\
+				plat/st/stm32mp1/stm32mp1_helper.S			\
+				plat/st/stm32mp1/stm32mp1_syscfg.c
+
+PLAT_BL_COMMON_SOURCES	+=	drivers/st/clk/stm32mp1_clk.c
+
+BL2_SOURCES		:=	drivers/io/io_storage.c					\
+				drivers/st/crypto/stm32_hash.c				\
+				plat/st/stm32mp1/stm32mp1_ssp.c
+
+ifeq (${STM32MP_UART_PROGRAMMER},1)
+BL2_SOURCES		+=	drivers/st/uart/stm32_uart.c				\
+				plat/st/common/stm32cubeprogrammer_uart.c
+endif
+
+ifeq (${STM32MP_USB_PROGRAMMER},1)
+BL2_SOURCES		+=	drivers/st/usb_dwc2/usb_dwc2.c				\
+				lib/usb/usb_core.c					\
+				lib/usb/usb_st_dfu.c					\
+				plat/st/common/stm32cubeprogrammer_usb.c		\
+				plat/st/stm32mp1/stm32mp1_usb.c
+endif
+
+BL2_DTSI		:=	stm32mp15-ssp-bl2.dtsi
+
+check_boot_ssp:
+	@if ([ ${STM32MP_UART_PROGRAMMER} = 1 ] && [ ${STM32MP_USB_PROGRAMMER} = 1 ]) || \
+	([ ${STM32MP_UART_PROGRAMMER} = 0 ] && [ ${STM32MP_USB_PROGRAMMER} = 0 ]); then \
+		echo "Error selecting serial boot device"; \
+		false; \
+	fi
+
+bl2: check_boot_ssp
+
+${BUILD_PLAT}/stm32mp1-ssp-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2
+	@echo "  SSP AS      stm32mp1.S"
+	${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+		-DDTB_BIN_PATH=\"$<\" \
+		-c plat/st/stm32mp1/stm32mp1.S -o $@