Merge changes from topic "st-bsec3" into integration

* changes:
  feat(stm32mp2): add BSEC and OTP support
  feat(st-bsec): add driver for the new IP version BSEC3
diff --git a/drivers/st/bsec/bsec3.c b/drivers/st/bsec/bsec3.c
new file mode 100644
index 0000000..a803a3a
--- /dev/null
+++ b/drivers/st/bsec/bsec3.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/bsec3_reg.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#define BSEC_IP_VERSION_1_0	U(0x10)
+#define BSEC_IP_ID_3		U(0x100033)
+
+#define MAX_NB_TRIES		U(3)
+
+/*
+ * IP configuration
+ */
+#define BSEC_OTP_MASK			GENMASK_32(4, 0)
+#define BSEC_OTP_BANK_SHIFT		U(5)
+#define BSEC_TIMEOUT_VALUE		U(0x800000) /* ~7sec @1.2GHz */
+
+/* Magic use to indicated valid SHADOW = 'B' 'S' 'E' 'C' */
+#define BSEC_MAGIC			U(0x42534543)
+
+#define OTP_MAX_SIZE			(STM32MP2_OTP_MAX_ID + U(1))
+
+struct bsec_shadow {
+	uint32_t magic;
+	uint32_t state;
+	uint32_t value[OTP_MAX_SIZE];
+	uint32_t status[OTP_MAX_SIZE];
+};
+
+static uint32_t otp_bank(uint32_t otp)
+{
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	return (otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT;
+}
+
+static uint32_t otp_bit_mask(uint32_t otp)
+{
+	return BIT(otp & BSEC_OTP_MASK);
+}
+
+/*
+ * bsec_get_status: return status register value.
+ */
+static uint32_t bsec_get_status(void)
+{
+	return mmio_read_32(BSEC_BASE + BSEC_OTPSR);
+}
+
+/*
+ * bsec_get_version: return BSEC version.
+ */
+static uint32_t bsec_get_version(void)
+{
+	return mmio_read_32(BSEC_BASE + BSEC_VERR) & BSEC_VERR_MASK;
+}
+
+/*
+ * bsec_get_id: return BSEC ID.
+ */
+static uint32_t bsec_get_id(void)
+{
+	return mmio_read_32(BSEC_BASE + BSEC_IPIDR);
+}
+
+static bool is_fuse_shadowed(uint32_t otp)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+	uint32_t bank_value;
+
+	bank_value = mmio_read_32(BSEC_BASE + BSEC_SFSR(bank));
+
+	if ((bank_value & otp_mask) != 0U) {
+		return true;
+	}
+
+	return false;
+}
+
+static void poll_otp_status_busy(void)
+{
+	uint32_t timeout = BSEC_TIMEOUT_VALUE;
+
+	while (((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) && (timeout != 0U)) {
+		timeout--;
+	}
+
+	if ((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) {
+		ERROR("BSEC timeout\n");
+		panic();
+	}
+}
+
+static uint32_t check_read_error(uint32_t otp)
+{
+	uint32_t status = bsec_get_status();
+
+	if ((status & BSEC_OTPSR_SECF) != 0U) {
+		VERBOSE("BSEC read %u single error correction detected\n", otp);
+	}
+
+	if ((status & BSEC_OTPSR_PPLF) != 0U) {
+		VERBOSE("BSEC read %u permanent programming lock detected.\n", otp);
+	}
+
+	if ((status & BSEC_OTPSR_PPLMF) != 0U) {
+		ERROR("BSEC read %u error 0x%x\n", otp, status);
+		return BSEC_ERROR;
+	}
+
+	if ((status & (BSEC_OTPSR_DISTURBF | BSEC_OTPSR_DEDF | BSEC_OTPSR_AMEF)) != 0U) {
+		ERROR("BSEC read %u error 0x%x with invalid FVR\n", otp, status);
+		return BSEC_RETRY;
+	}
+
+	return BSEC_OK;
+}
+
+static uint32_t check_program_error(uint32_t otp)
+{
+	uint32_t status = bsec_get_status();
+
+	if ((status & BSEC_OTPSR_PROGFAIL) != 0U) {
+		ERROR("BSEC program %u error 0x%x\n", otp, status);
+		return BSEC_RETRY;
+	}
+
+	return BSEC_OK;
+}
+
+static void check_reset_error(void)
+{
+	uint32_t status = bsec_get_status();
+
+	/* check initial status reporting */
+	if ((status & BSEC_OTPSR_BUSY) != 0U) {
+		VERBOSE("BSEC reset and busy when OTPSR read\n");
+	}
+	if ((status & BSEC_OTPSR_HIDEUP) != 0U) {
+		VERBOSE("BSEC upper fuse are not accessible (HIDEUP)\n");
+	}
+	if ((status & BSEC_OTPSR_OTPSEC) != 0U) {
+		VERBOSE("BSEC reset single error correction detected\n");
+	}
+	if ((status & BSEC_OTPSR_OTPNVIR) == 0U) {
+		VERBOSE("BSEC reset first fuse word 0 is detected zero\n");
+	}
+	if ((status & BSEC_OTPSR_OTPERR) != 0U) {
+		ERROR("BSEC reset critical error 0x%x\n", status);
+		panic();
+	}
+	if ((status & BSEC_OTPSR_FUSEOK) != BSEC_OTPSR_FUSEOK) {
+		ERROR("BSEC reset critical error 0x%x\n", status);
+		panic();
+	}
+}
+
+static bool is_bsec_write_locked(void)
+{
+	return (mmio_read_32(BSEC_BASE + BSEC_LOCKR) & BSEC_LOCKR_GWLOCK_MASK) != 0U;
+}
+
+/*
+ * bsec_probe: initialize BSEC driver.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_probe(void)
+{
+	uint32_t version = bsec_get_version();
+	uint32_t id = bsec_get_id();
+
+	if ((version != BSEC_IP_VERSION_1_0) || (id != BSEC_IP_ID_3)) {
+		ERROR("%s: version = 0x%x, id = 0x%x\n", __func__, version, id);
+		panic();
+	}
+
+	check_reset_error();
+
+	return BSEC_OK;
+}
+
+/*
+ * bsec_shadow_register: copy SAFMEM OTP to BSEC data.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+static uint32_t bsec_shadow_register(uint32_t otp)
+{
+	uint32_t result;
+	uint32_t i;
+	bool value;
+
+	result = bsec_read_sr_lock(otp, &value);
+	if (result != BSEC_OK) {
+		WARN("BSEC: %u Sticky-read bit read Error %u\n", otp, result);
+	} else if (value) {
+		VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", otp);
+	}
+
+	for (i = 0U; i < MAX_NB_TRIES; i++) {
+		mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp);
+
+		poll_otp_status_busy();
+
+		result = check_read_error(otp);
+		if (result != BSEC_RETRY) {
+			break;
+		}
+	}
+
+	return result;
+}
+
+/*
+ * bsec_write_otp: write a value in shadow OTP.
+ * val: value to program.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
+{
+	bool state;
+	uint32_t result;
+
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	if (!is_fuse_shadowed(otp)) {
+		return BSEC_ERROR;
+	}
+
+	if (is_bsec_write_locked()) {
+		return BSEC_WRITE_LOCKED;
+	}
+
+	result = bsec_read_sw_lock(otp, &state);
+	if (result != BSEC_OK) {
+		WARN("Shadow register is SW locked\n");
+		return result;
+	}
+
+	mmio_write_32(BSEC_BASE + BSEC_FVR(otp), val);
+
+	return BSEC_OK;
+}
+
+/*
+ * bsec_program_otp: program a bit in SAFMEM after the prog.
+ *	The OTP data is not refreshed.
+ * val: value to program.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
+{
+	uint32_t result;
+	uint32_t i;
+	bool value;
+
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	if (is_bsec_write_locked() == true) {
+		return BSEC_WRITE_LOCKED;
+	}
+
+	result = bsec_read_sp_lock(otp, &value);
+	if (result != BSEC_OK) {
+		WARN("BSEC: %u Sticky-prog bit read Error %u\n", otp, result);
+	} else if (value) {
+		WARN("BSEC: OTP locked, prog will be ignored\n");
+		return BSEC_WRITE_LOCKED;
+	}
+
+	mmio_write_32(BSEC_BASE + BSEC_WDR, val);
+
+	for (i = 0U; i < MAX_NB_TRIES; i++) {
+		mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp | BSEC_OTPCR_PROG);
+
+		poll_otp_status_busy();
+
+		result = check_program_error(otp);
+		if (result != BSEC_RETRY) {
+			break;
+		}
+	}
+
+	return result;
+}
+
+/*
+ * bsec_read_debug_conf: read debug configuration.
+ */
+uint32_t bsec_read_debug_conf(void)
+{
+	return mmio_read_32(BSEC_BASE + BSEC_DENR);
+}
+
+static uint32_t bsec_lock_register_set(uint32_t offset, uint32_t mask)
+{
+	uint32_t value = mmio_read_32(BSEC_BASE + offset);
+
+	/* The lock is already set */
+	if ((value & mask) != 0U) {
+		return BSEC_OK;
+	}
+
+	if (is_bsec_write_locked()) {
+		return BSEC_WRITE_LOCKED;
+	}
+
+	value |= mask;
+
+	mmio_write_32(BSEC_BASE + offset, value);
+
+	return BSEC_OK;
+}
+
+static bool bsec_lock_register_get(uint32_t offset, uint32_t mask)
+{
+	uint32_t value = mmio_read_32(BSEC_BASE + offset);
+
+	return (value & mask) != 0U;
+}
+
+/*
+ * bsec_set_sr_lock: set shadow-read lock.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_set_sr_lock(uint32_t otp)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	return bsec_lock_register_set(BSEC_SRLOCK(bank), otp_mask);
+}
+
+/*
+ * bsec_read_sr_lock: read shadow-read lock.
+ * otp: OTP number.
+ * value: read value (true or false).
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_read_sr_lock(uint32_t otp, bool *value)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+
+	assert(value != NULL);
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	*value = bsec_lock_register_get(BSEC_SRLOCK(bank), otp_mask);
+
+	return BSEC_OK;
+}
+
+/*
+ * bsec_set_sw_lock: set shadow-write lock.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_set_sw_lock(uint32_t otp)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	return bsec_lock_register_set(BSEC_SWLOCK(bank), otp_mask);
+}
+
+/*
+ * bsec_read_sw_lock: read shadow-write lock.
+ * otp: OTP number.
+ * value: read value (true or false).
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_read_sw_lock(uint32_t otp, bool *value)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+
+	assert(value != NULL);
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	*value = bsec_lock_register_get(BSEC_SWLOCK(bank), otp_mask);
+
+	return BSEC_OK;
+}
+
+/*
+ * bsec_set_sp_lock: set shadow-program lock.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_set_sp_lock(uint32_t otp)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	return bsec_lock_register_set(BSEC_SPLOCK(bank), otp_mask);
+}
+
+/*
+ * bsec_read_sp_lock: read shadow-program lock.
+ * otp: OTP number.
+ * value: read value (true or false).
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_read_sp_lock(uint32_t otp, bool *value)
+{
+	uint32_t bank = otp_bank(otp);
+	uint32_t otp_mask = otp_bit_mask(otp);
+
+	assert(value != NULL);
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	*value = bsec_lock_register_get(BSEC_SPLOCK(bank), otp_mask);
+
+	return BSEC_OK;
+}
+
+/*
+ * bsec_get_secure_state: read state in BSEC status register.
+ * return: secure state
+ */
+uint32_t bsec_get_secure_state(void)
+{
+	uint32_t state = BSEC_STATE_INVALID;
+	uint32_t status = bsec_get_status();
+	uint32_t bsec_sr = mmio_read_32(BSEC_BASE + BSEC_SR);
+
+	if ((status & BSEC_OTPSR_FUSEOK) == BSEC_OTPSR_FUSEOK) {
+		/* NVSTATE is only valid if FUSEOK */
+		uint32_t nvstates = (bsec_sr & BSEC_SR_NVSTATE_MASK) >> BSEC_SR_NVSTATE_SHIFT;
+
+		if (nvstates == BSEC_SR_NVSTATE_OPEN) {
+			state = BSEC_STATE_SEC_OPEN;
+		} else if (nvstates == BSEC_SR_NVSTATE_CLOSED) {
+			state = BSEC_STATE_SEC_CLOSED;
+		} else {
+			VERBOSE("%s nvstates = %u\n", __func__, nvstates);
+		}
+	}
+
+	return state;
+}
+
+/*
+ * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value
+ * val: read value.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_shadow_read_otp(uint32_t *val, uint32_t otp)
+{
+	assert(val != NULL);
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	*val = 0U;
+
+	if (is_bsec_write_locked()) {
+		return BSEC_WRITE_LOCKED;
+	}
+
+	if (!is_fuse_shadowed(otp)) {
+		uint32_t result = bsec_shadow_register(otp);
+
+		if (result != BSEC_OK) {
+			ERROR("BSEC: %u Shadowing Error %u\n", otp, result);
+			return result;
+		}
+	}
+
+	*val = mmio_read_32(BSEC_BASE + BSEC_FVR(otp));
+
+	return BSEC_OK;
+}
+
+/*
+ * bsec_read_otp: read an OTP data value.
+ * val: read value.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
+{
+	assert(val != NULL);
+	if (otp > STM32MP2_OTP_MAX_ID) {
+		panic();
+	}
+
+	return bsec_shadow_read_otp(val, otp);
+}
diff --git a/include/drivers/st/bsec3_reg.h b/include/drivers/st/bsec3_reg.h
new file mode 100644
index 0000000..177e30b
--- /dev/null
+++ b/include/drivers/st/bsec3_reg.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BSEC3_REG_H
+#define BSEC3_REG_H
+
+#include <lib/utils_def.h>
+
+/* BSEC REGISTER OFFSET (base relative) */
+#define BSEC_FVR(x)			(U(0x000) + 4U * (x))
+#define BSEC_SPLOCK(x)			(U(0x800) + 4U * (x))
+#define BSEC_SWLOCK(x)			(U(0x840) + 4U * (x))
+#define BSEC_SRLOCK(x)			(U(0x880) + 4U * (x))
+#define BSEC_OTPVLDR(x)			(U(0x8C0) + 4U * (x))
+#define BSEC_SFSR(x)			(U(0x940) + 4U * (x))
+#define BSEC_OTPCR			U(0xC04)
+#define BSEC_WDR			U(0xC08)
+#define BSEC_SCRATCHR0			U(0xE00)
+#define BSEC_SCRATCHR1			U(0xE04)
+#define BSEC_SCRATCHR2			U(0xE08)
+#define BSEC_SCRATCHR3			U(0xE0C)
+#define BSEC_LOCKR			U(0xE10)
+#define BSEC_JTAGINR			U(0xE14)
+#define BSEC_JTAGOUTR			U(0xE18)
+#define BSEC_DENR			U(0xE20)
+#define BSEC_UNMAPR			U(0xE24)
+#define BSEC_SR				U(0xE40)
+#define BSEC_OTPSR			U(0xE44)
+#define BSEC_WRCR			U(0xF00)
+#define BSEC_HWCFGR			U(0xFF0)
+#define BSEC_VERR			U(0xFF4)
+#define BSEC_IPIDR			U(0xFF8)
+#define BSEC_SIDR			U(0xFFC)
+
+/* BSEC_OTPCR register fields */
+#define BSEC_OTPCR_ADDR_MASK		GENMASK_32(8, 0)
+#define BSEC_OTPCR_ADDR_SHIFT		U(0)
+#define BSEC_OTPCR_PROG			BIT_32(13)
+#define BSEC_OTPCR_PPLOCK		BIT_32(14)
+#define BSEC_OTPCR_LASTCID_MASK		GENMASK_32(21, 19)
+#define BSEC_OTPCR_LASTCID_SHIFT	U(19)
+
+/* BSEC_LOCKR register fields */
+#define BSEC_LOCKR_GWLOCK_MASK		BIT_32(0)
+#define BSEC_LOCKR_GWLOCK_SHIFT		U(0)
+#define BSEC_LOCKR_DENLOCK_MASK		BIT_32(1)
+#define BSEC_LOCKR_DENLOCK_SHIFT	U(1)
+#define BSEC_LOCKR_HKLOCK_MASK		BIT_32(2)
+#define BSEC_LOCKR_HKLOCK_SHIFT		U(2)
+
+/* BSEC_DENR register fields */
+#define BSEC_DENR_LPDBGEN		BIT_32(0)
+#define BSEC_DENR_DBGENA		BIT_32(1)
+#define BSEC_DENR_NIDENA		BIT_32(2)
+#define BSEC_DENR_DEVICEEN		BIT_32(3)
+#define BSEC_DENR_HDPEN			BIT_32(4)
+#define BSEC_DENR_SPIDENA		BIT_32(5)
+#define BSEC_DENR_SPNIDENA		BIT_32(6)
+#define BSEC_DENR_DBGSWEN		BIT_32(7)
+#define BSEC_DENR_DBGENM		BIT_32(8)
+#define BSEC_DENR_NIDENM		BIT_32(9)
+#define BSEC_DENR_SPIDENM		BIT_32(10)
+#define BSEC_DENR_SPNIDENM		BIT_32(11)
+#define BSEC_DENR_CFGSDIS		BIT_32(12)
+#define BSEC_DENR_CP15SDIS_MASK		GENMASK_32(14, 13)
+#define BSEC_DENR_CP15SDIS_SHIFT	U(13)
+#define BSEC_DENR_LPDBGDIS		BIT_32(15)
+#define BSEC_DENR_ALL_MSK		GENMASK_32(15, 0)
+
+/* BSEC_SR register fields */
+#define BSEC_SR_BUSY			BIT_32(0)
+#define BSEC_SR_HVALID			BIT_32(1)
+#define BSEC_SR_RNGERR			BIT_32(2)
+#define BSEC_SR_HKWW_MASK		GENMASK_32(15, 8)
+#define BSEC_SR_HKWW_SHIFT		U(8)
+#define BSEC_SR_NVSTATE_MASK		GENMASK_32(31, 26)
+#define BSEC_SR_NVSTATE_SHIFT		U(26)
+#define BSEC_SR_NVSTATE_OPEN		U(0x16)
+#define BSEC_SR_NVSTATE_CLOSED		U(0x0D)
+#define BSEC_SR_NVSTATE_OTP_LOCKED	U(0x23)
+
+/* BSEC_OTPSR register fields */
+#define BSEC_OTPSR_BUSY			BIT_32(0)
+#define BSEC_OTPSR_FUSEOK		BIT_32(1)
+#define BSEC_OTPSR_HIDEUP		BIT_32(2)
+#define BSEC_OTPSR_OTPNVIR		BIT_32(4)
+#define BSEC_OTPSR_OTPERR		BIT_32(5)
+#define BSEC_OTPSR_OTPSEC		BIT_32(6)
+#define BSEC_OTPSR_PROGFAIL		BIT_32(16)
+#define BSEC_OTPSR_DISTURBF		BIT_32(17)
+#define BSEC_OTPSR_DEDF			BIT_32(18)
+#define BSEC_OTPSR_SECF			BIT_32(19)
+#define BSEC_OTPSR_PPLF			BIT_32(20)
+#define BSEC_OTPSR_PPLMF		BIT_32(21)
+#define BSEC_OTPSR_AMEF			BIT_32(22)
+
+/* BSEC_VERR register fields */
+#define BSEC_VERR_MASK			GENMASK_32(7, 0)
+
+#endif /* BSEC3_REG_H */
diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c
index 5f05f63..a7cce62 100644
--- a/plat/st/stm32mp2/bl2_plat_setup.c
+++ b/plat/st/stm32mp2/bl2_plat_setup.c
@@ -7,8 +7,10 @@
 #include <cdefs.h>
 #include <stdint.h>
 
+#include <common/debug.h>
 #include <plat/common/platform.h>
 
+#include <platform_def.h>
 #include <stm32mp_common.h>
 
 void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
@@ -25,4 +27,8 @@
 
 void bl2_el3_plat_arch_setup(void)
 {
+	if (stm32_otp_probe() != 0U) {
+		ERROR("OTP probe failed\n");
+		panic();
+	}
 }
diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk
index 6ea4638..0519b16 100644
--- a/plat/st/stm32mp2/platform.mk
+++ b/plat/st/stm32mp2/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2023, STMicroelectronics - All Rights Reserved
+# Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -46,6 +46,8 @@
 PLAT_BL_COMMON_SOURCES		+=	drivers/st/uart/${ARCH}/stm32_console.S
 PLAT_BL_COMMON_SOURCES		+=	plat/st/stm32mp2/${ARCH}/stm32mp2_helper.S
 
+PLAT_BL_COMMON_SOURCES		+=	drivers/st/bsec/bsec3.c
+
 BL2_SOURCES			+=	plat/st/stm32mp2/plat_bl2_mem_params_desc.c
 BL2_SOURCES			+=	plat/st/stm32mp2/bl2_plat_setup.c
 
diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h
index ee105de..56c62e1 100644
--- a/plat/st/stm32mp2/stm32mp2_def.h
+++ b/plat/st/stm32mp2/stm32mp2_def.h
@@ -158,6 +158,96 @@
 #define STM32MP_SDMMC3_BASE			U(0x48240000)
 
 /*******************************************************************************
+ * STM32MP2 BSEC / OTP
+ ******************************************************************************/
+/*
+ * 367 available OTPs, the other are masked
+ * - ECIES key: 368 to 375 (only readable by bootrom)
+ * - HWKEY: 376 to 383 (never reloadable or readable)
+ */
+#define STM32MP2_OTP_MAX_ID			U(0x16F)
+#define STM32MP2_MID_OTP_START			U(0x80)
+#define STM32MP2_UPPER_OTP_START		U(0x100)
+
+/* OTP labels */
+#define PART_NUMBER_OTP				"part-number-otp"
+#define PACKAGE_OTP				"package-otp"
+#define HCONF1_OTP				"otp124"
+#define NAND_OTP				"otp16"
+#define NAND2_OTP				"otp20"
+#define BOARD_ID_OTP				"board-id"
+#define UID_OTP					"uid-otp"
+#define LIFECYCLE2_OTP				"otp18"
+#define PKH_OTP					"otp144"
+#define ENCKEY_OTP				"otp260"
+
+/* OTP mask */
+/* PACKAGE */
+#define PACKAGE_OTP_PKG_MASK			GENMASK_32(2, 0)
+#define PACKAGE_OTP_PKG_SHIFT			U(0)
+
+/* IWDG OTP */
+#define HCONF1_OTP_IWDG_HW_POS			U(0)
+#define HCONF1_OTP_IWDG_FZ_STOP_POS		U(1)
+#define HCONF1_OTP_IWDG_FZ_STANDBY_POS		U(2)
+
+/* NAND OTP */
+/* NAND parameter storage flag */
+#define NAND_PARAM_STORED_IN_OTP		BIT_32(31)
+
+/* NAND page size in bytes */
+#define NAND_PAGE_SIZE_MASK			GENMASK_32(30, 29)
+#define NAND_PAGE_SIZE_SHIFT			U(29)
+#define NAND_PAGE_SIZE_2K			U(0)
+#define NAND_PAGE_SIZE_4K			U(1)
+#define NAND_PAGE_SIZE_8K			U(2)
+
+/* NAND block size in pages */
+#define NAND_BLOCK_SIZE_MASK			GENMASK_32(28, 27)
+#define NAND_BLOCK_SIZE_SHIFT			U(27)
+#define NAND_BLOCK_SIZE_64_PAGES		U(0)
+#define NAND_BLOCK_SIZE_128_PAGES		U(1)
+#define NAND_BLOCK_SIZE_256_PAGES		U(2)
+
+/* NAND number of block (in unit of 256 blocks) */
+#define NAND_BLOCK_NB_MASK			GENMASK_32(26, 19)
+#define NAND_BLOCK_NB_SHIFT			U(19)
+#define NAND_BLOCK_NB_UNIT			U(256)
+
+/* NAND bus width in bits */
+#define NAND_WIDTH_MASK				BIT_32(18)
+#define NAND_WIDTH_SHIFT			U(18)
+
+/* NAND number of ECC bits per 512 bytes */
+#define NAND_ECC_BIT_NB_MASK			GENMASK_32(17, 15)
+#define NAND_ECC_BIT_NB_SHIFT			U(15)
+#define NAND_ECC_BIT_NB_UNSET			U(0)
+#define NAND_ECC_BIT_NB_1_BITS			U(1)
+#define NAND_ECC_BIT_NB_4_BITS			U(2)
+#define NAND_ECC_BIT_NB_8_BITS			U(3)
+#define NAND_ECC_ON_DIE				U(4)
+
+/* NAND number of planes */
+#define NAND_PLANE_BIT_NB_MASK			BIT_32(14)
+
+/* NAND2 OTP */
+#define NAND2_PAGE_SIZE_SHIFT			U(16)
+
+/* NAND2 config distribution */
+#define NAND2_CONFIG_DISTRIB			BIT_32(0)
+#define NAND2_PNAND_NAND2_SNAND_NAND1		U(0)
+#define NAND2_PNAND_NAND1_SNAND_NAND2		U(1)
+
+/* MONOTONIC OTP */
+#define MAX_MONOTONIC_VALUE			U(32)
+
+/* UID OTP */
+#define UID_WORD_NB				U(3)
+
+/* Lifecycle OTP */
+#define SECURE_BOOT_CLOSED_SECURE		GENMASK_32(3, 0)
+
+/*******************************************************************************
  * STM32MP2 TAMP
  ******************************************************************************/
 #define PLAT_MAX_TAMP_INT			U(5)