Commit 5674eaca authored by Alexandre Bourdiol's avatar Alexandre Bourdiol Committed by Christopher Friedt
Browse files

soc: arm: stm32h7: rework STM32H7 dual core boot



It happens that CM7 wakeups CM4, before CM4 goes to sleep.
Thus when CM4 goes to sleep,
there no more wakeup from CM7. And CM4 hangs.
For a simple synchronisation implementation,
CM4 doesn't go to sleep any more,
instead it waits (active wait) for CM7 to take HSEM
(meaning that clock configuration is finished).

Fixes #38069

Signed-off-by: default avatarAlexandre Bourdiol <alexandre.bourdiol@st.com>
parent 6272d303
Loading
Loading
Loading
Loading
+11 −45
Original line number Diff line number Diff line
@@ -22,39 +22,6 @@
#include <arch/arm/aarch32/cortex_m/cmsis.h>
#include "stm32_hsem.h"

void stm32h7_m4_boot_stop(void)
{
	/*
	 * Domain D2 goes to STOP mode (Cortex-M4 in deep-sleep) waiting for
	 * Cortex-M7 to perform system initialization (system clock config,
	 * external memory configuration.. )
	 */

	 /* Clear pending events if any */
	 __SEV();
	 __WFE();

	 /* Select the domain Power Down DeepSleep */
	 LL_PWR_SetRegulModeDS(LL_PWR_REGU_DSMODE_MAIN);
	 /* Keep DSTOP mode when D2 domain enters Deepsleep */
	 LL_PWR_CPU_SetD2PowerMode(LL_PWR_CPU_MODE_D2STOP);
	 LL_PWR_CPU2_SetD2PowerMode(LL_PWR_CPU2_MODE_D2STOP);
	 /* Set SLEEPDEEP bit of Cortex System Control Register */
	 LL_LPM_EnableDeepSleep();

	 /* Ensure that all instructions done before entering STOP mode */
	 __DSB();
	 __ISB();
	 /* Request Wait For Event */
	 __WFE();

	 /* Reset SLEEPDEEP bit of Cortex System Control Register,
	  * the following LL API Clear SLEEPDEEP bit of Cortex
	  * System Control Register
	  */
	LL_LPM_EnableSleep();
}

/**
 * @brief Perform basic hardware initialization at boot.
 *
@@ -81,21 +48,20 @@ static int stm32h7_m4_init(const struct device *arg)

	irq_unlock(key);

	/*HW semaphore Clock enable*/
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM);

	/* In case CM4 has not been forced boot by CM7,
	 * CM4 needs to be stopped until CM7 has setup clock configuration
	 * CM4 needs to wait until CM7 has setup clock configuration
	 */
	if (!LL_RCC_IsCM4BootForced()) {
		/* Activate HSEM notification for Cortex-M4 */
		LL_HSEM_EnableIT_C2IER(HSEM, CFG_HW_ENTRY_STOP_MODE_MASK_SEMID);

		/* Boot and enter stop mode */
		stm32h7_m4_boot_stop();

		/* Clear HSEM flag */
		LL_HSEM_ClearFlag_C2ICR(HSEM, CFG_HW_ENTRY_STOP_MODE_MASK_SEMID);
		/*
		 * Domain D2 is waiting for Cortex-M7 to perform
		 * system initialization
		 * (system clock config, external memory configuration.. ).
		 * End of system initialization is reached when CM7 takes HSEM.
		 */
		LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM);
		while ((HSEM->RLR[CFG_HW_ENTRY_STOP_MODE_SEMID] & HSEM_R_LOCK)
				!= HSEM_R_LOCK)
			;
	}

	return 0;
+3 −21
Original line number Diff line number Diff line
@@ -30,29 +30,11 @@ static int stm32h7_m4_wakeup(const struct device *arg)
	LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);

	if (READ_BIT(SYSCFG->UR1, SYSCFG_UR1_BCM4)) {
		/* CM4 is started at boot in parallel of CM7
		 * but CM4 should set itself into stop mode,
		 * waiting for CM7 clock initialization.
		/* Cortex-M4 is waiting for end of system initialization made by
		 * Cortex-M7. This initialization is now finished,
		 * then Cortex-M7 takes HSEM so that CM4 can continue running.
		 */
		int timeout;

		/*
		 * When system initialization is finished, Cortex-M7 will
		 * release Cortex-M4  by means of HSEM notification
		 */

		/*Take HSEM */
		LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID);
		/*Release HSEM in order to notify the CPU2(CM4)*/
		LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);

		/* wait until CPU2 wakes up from stop mode */
		timeout = 0xFFFF;
		while ((LL_RCC_D2CK_IsReady() == 0) && ((timeout--) > 0)) {
		}
		if (timeout < 0) {
			return -EIO;
		}
	} else {
		/* CM4 is not started at boot, start it now */
		LL_RCC_ForceCM4Boot();