stm32mp1: add watchdog support

Introduce driver for STM32 IWDG peripheral (Independent Watchdog).
It is configured according to device tree content and should be enabled
from there.
The watchdog is not started by default. It can be started after an HW
reset if the dedicated OTP is fused.

The watchdog also needs to be frozen if a debugger is attached.
This is done by configuring the correct bits in DBGMCU.
This configuration is allowed by checking BSEC properties.

An increase of BL2 size is also required when adding this new code.

Change-Id: Ide7535d717885ce2f9c387cf17afd8b5607f3e7f
Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 340c7fb..886a8f3 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -8,6 +8,7 @@
 
 #include <platform_def.h>
 
+#include <drivers/st/stm32_iwdg.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
 #define MAP_SRAM	MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
@@ -66,3 +67,78 @@
 
 	return GPIOA + (bank - GPIO_BANK_A);
 }
+
+uint32_t stm32_iwdg_get_instance(uintptr_t base)
+{
+	switch (base) {
+	case IWDG1_BASE:
+		return IWDG1_INST;
+	case IWDG2_BASE:
+		return IWDG2_INST;
+	default:
+		panic();
+	}
+}
+
+uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst)
+{
+	uint32_t iwdg_cfg = 0U;
+	uint32_t otp_value;
+
+#if defined(IMAGE_BL2)
+	if (bsec_shadow_register(HW2_OTP) != BSEC_OK) {
+		panic();
+	}
+#endif
+
+	if (bsec_read_otp(&otp_value, HW2_OTP) != BSEC_OK) {
+		panic();
+	}
+
+	if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_HW_POS)) != 0U) {
+		iwdg_cfg |= IWDG_HW_ENABLED;
+	}
+
+	if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS)) != 0U) {
+		iwdg_cfg |= IWDG_DISABLE_ON_STOP;
+	}
+
+	if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS)) != 0U) {
+		iwdg_cfg |= IWDG_DISABLE_ON_STANDBY;
+	}
+
+	return iwdg_cfg;
+}
+
+#if defined(IMAGE_BL2)
+uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags)
+{
+	uint32_t otp;
+	uint32_t result;
+
+	if (bsec_shadow_read_otp(&otp, HW2_OTP) != BSEC_OK) {
+		panic();
+	}
+
+	if ((flags & IWDG_DISABLE_ON_STOP) != 0U) {
+		otp |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS);
+	}
+
+	if ((flags & IWDG_DISABLE_ON_STANDBY) != 0U) {
+		otp |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS);
+	}
+
+	result = bsec_write_otp(otp, HW2_OTP);
+	if (result != BSEC_OK) {
+		return result;
+	}
+
+	/* Sticky lock OTP_IWDG (read and write) */
+	if (!bsec_write_sr_lock(HW2_OTP, 1U) ||
+	    !bsec_write_sw_lock(HW2_OTP, 1U)) {
+		return BSEC_LOCK_FAIL;
+	}
+
+	return BSEC_OK;
+}
+#endif