From 3d1b2b0a2095828c8c9bce4ae5960b51a882a653 Mon Sep 17 00:00:00 2001
From: Lionel Debieve <lionel.debieve@st.com>
Date: Tue, 7 Jul 2020 15:33:57 +0200
Subject: [PATCH] stm32mp1: Use SCMI reset to manage MCU hold boot

Adding the MCU hold boot management through a SCMI dedicated
reset domain. Remove the associated RCC SMC service.

Minor: Fix the panic when trying to checking access to avoid
non-secure world panic trigger.

Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
Change-Id: I70fe10602eaa0e76ef2aad9cd8c1b0454dae190a
---
 drivers/st/reset/stm32mp1_reset.c            | 18 +++++++++++++++++-
 include/drivers/st/stm32mp_reset.h           |  9 ++++++++-
 include/dt-bindings/reset/stm32mp1-resets.h  |  2 ++
 plat/st/stm32mp1/stm32mp1_scmi.c             | 12 ++++++++++++
 plat/st/stm32mp1/stm32mp1_shared_resources.c |  1 +
 5 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
index 98c8dcf71..287d398ab 100644
--- a/drivers/st/reset/stm32mp1_reset.c
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -67,3 +67,19 @@ int stm32mp_reset_deassert(uint32_t id, unsigned int to_us)
 
 	return 0;
 }
+
+void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert)
+{
+	uintptr_t rcc_base = stm32mp_rcc_base();
+
+	/*
+	 * The RCC_MP_GCR is a read/write register.
+	 * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit
+	 * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit
+	 */
+	if (assert_not_deassert) {
+		mmio_clrbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
+	} else {
+		mmio_setbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
+	}
+}
diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h
index 84448050d..397079801 100644
--- a/include/drivers/st/stm32mp_reset.h
+++ b/include/drivers/st/stm32mp_reset.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -47,4 +47,11 @@ static inline void stm32mp_reset_release(uint32_t reset_id)
 	(void)stm32mp_reset_deassert(reset_id, 0U);
 }
 
+/*
+ * Manage reset control for the MCU reset
+ *
+ * @assert_not_deassert: reset requested state
+ */
+void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert);
+
 #endif /* STM32MP_RESET_H */
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
index bc71924fa..f3a0ed317 100644
--- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -7,6 +7,7 @@
 #ifndef _DT_BINDINGS_STM32MP1_RESET_H_
 #define _DT_BINDINGS_STM32MP1_RESET_H_
 
+#define MCU_HOLD_BOOT_R	2144
 #define LTDC_R		3072
 #define DSI_R		3076
 #define DDRPERFM_R	3080
@@ -117,5 +118,6 @@
 #define RST_SCMI0_RNG1		8
 #define RST_SCMI0_MDMA		9
 #define RST_SCMI0_MCU		10
+#define RST_SCMI0_MCU_HOLD_BOOT	11
 
 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
index 80faf0c6e..31c9cd37c 100644
--- a/plat/st/stm32mp1/stm32mp1_scmi.c
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -124,6 +124,7 @@ static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
 	RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
 	RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
 	RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+	RESET_CELL(RST_SCMI0_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"),
 };
 
 struct scmi_agent_resources {
@@ -388,6 +389,10 @@ int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
 		return SCMI_NOT_FOUND;
 	}
 
+	if (rstd->reset_id == MCU_HOLD_BOOT_R) {
+		return SCMI_NOT_SUPPORTED;
+	}
+
 	if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
 		return SCMI_DENIED;
 	}
@@ -423,6 +428,13 @@ int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
 		return SCMI_DENIED;
 	}
 
+	if (rstd->reset_id == MCU_HOLD_BOOT_R) {
+		VERBOSE("SCMI MCU reset %s\n",
+			assert_not_deassert ? "set" : "release");
+		stm32mp_reset_assert_deassert_to_mcu(assert_not_deassert);
+		return SCMI_SUCCESS;
+	}
+
 	if (assert_not_deassert) {
 		VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
 		stm32mp_reset_set(rstd->reset_id);
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
index 14e4fcc03..f6c8b3bb4 100644
--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -562,6 +562,7 @@ bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
 		shres_id = STM32MP1_SHRES_I2C6;
 		break;
 	case MCU_R:
+	case MCU_HOLD_BOOT_R:
 		shres_id = STM32MP1_SHRES_MCU;
 		break;
 	case MDMA_R:
-- 
GitLab