Hi,
We have an issue when enter suspend when running m7. The firmware is controlled by the rpmsg on the linux side and we have implemented a signal to set the m7 to enter GPC stop mode. According to i.MX 8M Plus Applications Processor Reference Manual, Rev. 1, 06/2021. GPC_SLPCR page.605. We set GPC_SLPCR register and another using gpc.h from MCUXpresso. We have also read the AN13400 to try to understand the limits for stop,wait and dsm with (Fast-Wake-up and non-Fast-Wake-up ).
Our goal is to enter suspend on both M and A side with PMIC_STBY_REQ set to high state. A has all wakeup functions and wake up first than wake up the M side.
We have so far got almost everting working except for PMIC_STBY_REQ set to high state. when we have gpc_stopmode with Fast-Wake-up and we understand that the PLL need to be stopped to enter DSM. Here is the m side code that running and we have tried a few diffrent combinations of gpc_lpm_config_t already but this is the one we got to wakeup the M from A:
static void suspend()
{
(void)PRINTF("Entering suspend\r\n");
gpc_lpm_config_t config;
config.enCpuClk = false;
config.enFastWakeUp = true;
config.enDsmMask = false;
config.enWfiMask = false;
config.enVirtualPGCPowerdown = true;
config.enVirtualPGCPowerup = true;
/* Lower the root clock speed to 24 Mhz, required to survive deep sleep. */
if (CLOCK_GetRootMux(kCLOCK_RootM7) != kCLOCK_M7RootmuxOsc24M)
{
CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M);
CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U);
}
(void)PRINTF("Entering GPC stop mode\r\n");
/* Stop all clocks in Vcore domain but preserve RAM */
GPC_EnterStopMode(GPC, &config); /* Interrupt (e.g. rpmsg) required to pass this barrier */
/* Go into idle mode. Now it's safe to enter deep sleep. */
(void)PRINTF("Leaving GPC stop mode\r\n");
/* Any future last-moment pre-sleep actions could be taken here. */
#ifdef BOARD_DEBUG_UART_TYPE
DbgConsole_Deinit(); /* If needed, the UART port must be redeclared as 24Mhz. */
#endif
/* Do nothing so that the idle hook function is triggered before the A core goes into suspend. */
__DSB();
__ISB();
__WFI();
/* Any future resume actions could be taken here. */
/* Re-enable debug prints */
#ifdef BOARD_DEBUG_UART_TYPE
DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE,
BOARD_DEBUG_UART_CLK_FREQ);
#endif
if (CLOCK_GetRootMux(kCLOCK_RootM7) != kCLOCK_M7RootmuxSysPll1)
{
CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U); /* Reset root clock to 800M */
CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1); /* Switch Cortex-M7 to SYSTEM PLL1 */
}
GPC->LPCR_M7 = GPC->LPCR_M7 & (~GPC_LPCR_M7_LPM0_MASK);
(void)PRINTF("Leaving suspend\r\n");
}
Questions
Additional data
A core is running
Poky (Yocto Project Reference Distro) 4.0.13
Linux 6.1.22
M firmware
It is based on the RPMsg-Lite pingpong sample from the FreeRTOS-based MCUXpresso SDK. we are using 2 gpios as outputs no other interface is active (uart for debug on for VAR-DT8MCustomBoard when we not using our hardware Host Monitor x).
load the m7 firmware in uboot (ddr)
已解决! 转到解答。
Hi,
We investigated it some more and found out that removing the CLOCK_ControlGate in board.c was the code that prevent the unit from enter DSM. (there was pll1 2 and 3 and if one was enable the system does not enter DSM)
//CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll); /* Enable the CCGR gate for SysPLL1 in Domain 1 */
we removed all other clocks in clock_config.c except for the pll1 root clock that seems to minimize the current consumption even more(or maybe it did not do anything, we get a bit diffrent result at the moment but we think it is related to A core device tree settings) but it had little affect compare to just enter stop_mode and not been able to go to dsm mode. (on 24V for host monitor x platform, we got with just enter stop mode current consumtion of 170-180mA and without m7 fimware running or with the code provided in this topic we got it down to 10-40mA (depends on if we have a modem on or not and maybe some pimux that need to be adjusted to avoid current leaks in suspend)).
Thanks for your help @Zhiming_Liu
the parts that help us continue trying to get it to work was that you confirmed that PMIC_STBY_REQ could be set and todays post that only pll1 root clock was needed to run the m7 core.
Hi @Rikardo
Is it only in DSM that PMIC_STBY_REQ can be set to high state(1) from A side?
-->From some previous case answer in internal box, the answer is yes.
Is it possible to wakeup the M side trough the rpmsg interrupts when it is in DSM? (we can not set any gpio wakeup pins to M side)
-->This is possible, normally we unmask the MU interrupt in A53 side and then M7 can wake up A53. It's same for waking up M7, the interrupts in MU are bi-directional. M core can sent interrupt to A core , and A core can also sent interrupt to M core with MU.You should unmask the MU bit in GPC_IMRx_M7, but this bit is not officially released in RM.
Why is it not possible to wakeup when in the GPC stopmode? Instead we need to send a any rpmsg to leave the GPC stop mode function to enter __DSB,
-->The interruprt could be masked in GPC_IMRx_M7 as the RM said that any M7 interrupt can wake up M7 from LPM. The process of sending rpmsg will use Message Unit to generate interrupt to M7, i think this is reasonable why you need to send rpmsg. So the MU interrupt should have been unmasked in GPC_IMRx_M7.You can trigger interrupt0 on Linux side in Message Unit hardware to wake up M7.
Hi @Zhiming_Liu,
We got it to work as we wanted with PMIC_STBY_REQ set to high and we can wakeup trough the rsmsg bus.
Still we are a bit unsure that our configuration can be used safely. I have attached the two files we have changed to make use of dsm. also we needed to set the dsm_mask to true so this is the new updated code:
static void suspend()
{
(void)PRINTF("Entering suspend\r\n");
gpc_lpm_config_t config;
config.enCpuClk = false;
config.enFastWakeUp = true;
config.enDsmMask = true;
config.enWfiMask = false;
config.enVirtualPGCPowerdown = true;
config.enVirtualPGCPowerup = true;
/* Lower the root clock speed to 24 Mhz, required to survive deep sleep. */
if (CLOCK_GetRootMux(kCLOCK_RootM7) != kCLOCK_M7RootmuxOsc24M)
{
CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M);
CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U);
}
(void)PRINTF("Entering GPC stop mode\r\n");
/* Stop all clocks in Vcore domain but preserve RAM */
GPC_EnterStopMode(GPC, &config); /* Interrupt (e.g. rpmsg) required to pass this barrier */
/* Go into idle mode. Now it's safe to enter deep sleep. */
(void)PRINTF("Leaving GPC stop mode\r\n");
/* Any future last-moment pre-sleep actions could be taken here. */
#ifdef BOARD_DEBUG_UART_TYPE
DbgConsole_Deinit(); /* If needed, the UART port must be redeclared as 24Mhz. */
#endif
/* Do nothing so that the idle hook function is triggered before the A core goes into suspend. */
__DSB();
__ISB();
__WFI();
/* Any future resume actions could be taken here. */
/* Re-enable debug prints */
#ifdef BOARD_DEBUG_UART_TYPE
DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE,
BOARD_DEBUG_UART_CLK_FREQ);
#endif
if (CLOCK_GetRootMux(kCLOCK_RootM7) != kCLOCK_M7RootmuxSysPll1)
{
CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U); /* Reset root clock to 800M */
CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1); /* Switch Cortex-M7 to SYSTEM PLL1 */
}
GPC->LPCR_M7 = GPC->LPCR_M7 & (~GPC_LPCR_M7_LPM0_MASK);
(void)PRINTF("Leaving suspend\r\n");
}
Hi,
We investigated it some more and found out that removing the CLOCK_ControlGate in board.c was the code that prevent the unit from enter DSM. (there was pll1 2 and 3 and if one was enable the system does not enter DSM)
//CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll); /* Enable the CCGR gate for SysPLL1 in Domain 1 */
we removed all other clocks in clock_config.c except for the pll1 root clock that seems to minimize the current consumption even more(or maybe it did not do anything, we get a bit diffrent result at the moment but we think it is related to A core device tree settings) but it had little affect compare to just enter stop_mode and not been able to go to dsm mode. (on 24V for host monitor x platform, we got with just enter stop mode current consumtion of 170-180mA and without m7 fimware running or with the code provided in this topic we got it down to 10-40mA (depends on if we have a modem on or not and maybe some pimux that need to be adjusted to avoid current leaks in suspend)).
Thanks for your help @Zhiming_Liu
the parts that help us continue trying to get it to work was that you confirmed that PMIC_STBY_REQ could be set and todays post that only pll1 root clock was needed to run the m7 core.
Hi @Zhiming_Liu,
Thanks for your answers. Now it is a bit more hopeful that we can enter "dsm" mode.
Is there any example of the bare minimum setup of clocks and plls to run m7 or m4 on? Any tricks to know that we have stopped all plls to enter dsm with fastmap in case that is the only one we can use? in AN13400 5.5.5 Disable System PLLs there is an example code but we cannot understand how it is supposed to work.
Right now, we have in our clock_config.c only the 'CLOCK_M7RootmuxSysPll1' and comment out the reset, it seems to get the unit a bit lower in current consumption but still it does not set the PMIC_STBY_REQ to high.
Is there any example of the bare minimum setup of clocks and plls to run m7 or m4 on? Any tricks to know that we have stopped all plls to enter dsm with fastmap in case that is the only one we can use? in AN13400 5.5.5 Disable System PLLs there is an example code but we cannot understand how it is supposed to work.
-->The example code is in ATF:https://github.com/nxp-imx/imx-atf/blob/lf_v2.6/plat/imx/imx8m/imx8mp/imx8mp_lpa_psci.c
Right now, we have in our clock_config.c only the 'CLOCK_M7RootmuxSysPll1' and comment out the reset, it seems to get the unit a bit lower in current consumption but still it does not set the PMIC_STBY_REQ to high.
-->
For PMIC_STBY_REQ:
On i.MX8MP, the power management code are in ATF(Arm-Trusted-Firmware). PMIC_STBY_REQ signal will be assert when system enters DSM mode in ATF code. Please check GPC chapter in RM for DSM description.
In general, when both A core and M core are in STOP mode (Or A core in STOP, M core is not running) and all PLLs are disabled and bypassed, system can enter DSM mode.
When all conditions meet (including GPC_SLPCR[VSTBY] is set), system will enter DSM after execute wfi command.
ATF Code location:
plat/imx/imx8m/imx8mp/imx8mp_psci.c
plat/imx/imx8m/gpc_common.c
plat/imx/imx8m/imx8m_psci_common.c
For PMIC_ON_REQ:
The power key driver is in kernel:
drivers/input/keyboard/snvs_pwrkey.c
drivers/input/keyboard/imx_sc_pwrkey.c