imx8mp suspend into DSM with m7 in GPC_EnterStopMode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx8mp suspend into DSM with m7 in GPC_EnterStopMode

Jump to solution
4,699 Views
Rikardo
Contributor II

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

  • Is it only in DSM that PMIC_STBY_REQ can be set to high state(1) from A side?
  • 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)
  • 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, but if we skip using GPC_stopmode the M will not be able to wakeup or if we are in the GPC_stopmode it will not wake up either.
    what is the minimum amount of clocks(Pll) additional to RootM7(pll1), that is needed in case we have started more clocks than we need.


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)

 

 

0 Kudos
Reply
1 Solution
4,576 Views
Rikardo
Contributor II

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.

View solution in original post

0 Kudos
Reply
5 Replies
4,660 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

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.

Zhiming_Liu_0-1716542020776.png

 

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.

Zhiming_Liu_1-1716542764441.png

 

0 Kudos
Reply
4,639 Views
Rikardo
Contributor II

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");
}

 

0 Kudos
Reply
4,577 Views
Rikardo
Contributor II

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.

0 Kudos
Reply
4,640 Views
Rikardo
Contributor II

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.

 

 

 

0 Kudos
Reply
4,608 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

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

Zhiming_Liu_0-1717036675768.png

 

 

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

0 Kudos
Reply