Verdin imx8mp: CTRL_SLEEP_MOCI remains high during sleep mode

Hello,

on my Verdin imx8mp I am trying to get the CTRL_SLEEP_MOCI pin to get high while the SoM is running, while to get low when the SoM gets in sleep mode. Unfortunately all my attempts are ending in the pin to be either always high or always low.

Here the original device tree snips of codes related to the CTRL_SLEEP_MOCI pin

/*
* By default we enable CTRL_SLEEP_MOCI#, this is required to have
* peripherals on the carrier board powered.
* If more granularity or power saving is required this can be disabled
* in the carrier board device tree files.
/
reg_force_sleep_moci: regulator-force-sleep-moci {
compatible = “regulator-fixed”;
enable-active-high;
/
Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
regulator-always-on;
regulator-boot-on;
regulator-name = “CTRL_SLEEP_MOCI#”;
};

pinctrl_ctrl_sleep_moci: ctrlsleepmocigrp {
fsl,pins =
<MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x1c4>; /* SODIMM 256 */
};

&gpio4 {
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
};

How should the device tree be changed to get the desired behavior?

Project info:

  • Yocto project based on Toradex Scarthgap manifest (./repo init -u git://git.toradex.com/toradex-manifest.git -b scarthgap-7.x.y -m tdxref/default.xml).
  • Kernel version: 6.6.84-7.3.0-devel #1 SMP PREEMPT Wed Apr 30 17:53:10 UTC 2025

Best regards,
Loris

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello Loris,

Thank you for your detailed description.

The desired CTRL_SLEEP_MOCI# behavior (high when the SoM is running, low in sleep) is supported as of BSP 6.4+. Since you are using a recent kernel and the Scarthgap Yocto (BSP 7.x.y), you should be able to achieve this, but a few critical points should be adjusted in your device tree.

Main Factors for CTRL_SLEEP_MOCI# Operation

  1. GPIO Polarity:
    CTRL_SLEEP_MOCI# (note the #) means “active low.” The SoM asserts this pin low in sleep mode.
    • The physical behavior: High in run, Low (asserted) in sleep
  2. Device Tree Regulator Configuration:
    You want the regulator to be disabled (output low) during system suspend and enabled (output high) during normal operation.
  3. Pinmux and GPIO Configuration:
    The pin must remain configured as output and under kernel control for sleep transitions.

1. Regulator Configuration

Current State:

You are using

enable-active-high;
gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
regulator-always-on;
regulator-boot-on;
  • regulator-always-on keeps the regulator always ON; it will never go off in suspend.

Fix:

Remove regulator-always-on and (optionally) regulator-boot-on.

  • DO NOT set regulator-always-on if you want the pin to drop in suspend.

Use this:

reg_force_sleep_moci: regulator-force-sleep-moci {
    compatible = "regulator-fixed";
    enable-active-high;
    /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
    gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
    regulator-name = "CTRL_SLEEP_MOCI#";
    /* regulator-always-on; <-- REMOVE THIS */
    /* regulator-boot-on;   <-- REMOVE THIS */
};

This way, the driver is allowed to disable the GPIO (= assert low) during suspend.


2. Pinmux

Your pinmux is correct, just ensure nothing else overrides this pin.

pinctrl_ctrl_sleep_moci: ctrlsleepmocigrp {
    fsl,pins =
        <MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x1c4>; /* SODIMM 256 */
};

3. Regulator Consumers

The proper functioning depends on something marking the regulator as required only during normal operation, and letting the kernel disable it during suspend.

Example:

  • Ensure any device in the device tree that “uses” this supply lists regulator-force-sleep-moci as its supply.
    &i2c1 {
        vcc-supply = <&reg_force_sleep_moci>;
        /* ... */
    };
    
  • Or, if you don’t want to control a specific device, you can use the default configuration and the kernel should disable unneeded regulators in suspend.

4. Kernel Power Management

The kernel’s power management must be enabled and SoM must actually suspend for the pin to change.

  • Use echo mem > /sys/power/state to test sleep.
  • The CTRL_SLEEP_MOCI# pin should go low when suspended and return high when resumed.

Summary of Your Required Device Tree Changes

  1. Remove regulator-always-on; and regulator-boot-on; from reg_force_sleep_moci.
  2. Ensure the gpio line is correct and pinmux is configured as output.
  3. Make sure any critical peripherals on your carrier depend on reg_force_sleep_moci.
  4. Confirm sleep state is working (i.e., SoM actually enters suspend).

Useful Links

Would you like a complete example device tree overlay or more details on how to test the state change in Linux?

Best regards,
Toradex AI Assistant.

I tired to disable it and create a new one with different name and no regulator-always-on with an overlay, but the peripherals connected to it after a while turns off, and when I put the SoM in sleep mode it does not turn down.

The only way that I found till now to rich the desired behavior is to associate the gpio to a gpio-led driver

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>

/ {
    compatible = "toradex,verdin-imx8mp";
};


&reg_force_sleep_moci {
    status = "disabled";
};

&{/} {
    carrier_pwr_enable: carrier_pwr_enable {
		compatible = "gpio-leds";
		
		peripheral_power_en {
			label = "carrier-peripheral-power-enable";
			gpios = <&gpio4 29 0>;
			linux,default-trigger = "default-on";
			default-state = "on";
		};
	};
};

I am open to a more correct solution if it does work.

Best regards,
Loris

Dear @loris.teq,

That looks like a neat workaround. I would however suggest following what has been done on the dahlia device tree.

Should you have your own device tree for your carrier board, than you will have to disable reg_force_sleep_moci, as shown in the following dahlia device tree:
https://git.toradex.com/cgit/linux-toradex.git/tree/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi?h=toradex_6.6-2.2.x-imx#n172
After that you will need to implement a regulator for each device, which is connected to that voltage level. Here is an example on how it is done for a USB hub:
https://git.toradex.com/cgit/linux-toradex.git/tree/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi?h=toradex_6.6-2.2.x-imx#n36
The mentioned USB hub is then used over here:
https://git.toradex.com/cgit/linux-toradex.git/tree/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi?h=toradex_6.6-2.2.x-imx#n232
As a second example there is PCIe:
https://git.toradex.com/cgit/linux-toradex.git/tree/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi?h=toradex_6.6-2.2.x-imx#n45
which is then again used here:
https://git.toradex.com/cgit/linux-toradex.git/tree/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi?h=toradex_6.6-2.2.x-imx#n144
If you implement all your devices this way, the sleep_moci signal should behave correctly.
Alternatively you could give the dahlia device tree a try and see whether your signal behaves correctly in that case.

Best regards,
Collin