Power Saving on Verding imx8mm on custom carrier

Hi,

I am looking to reduce power consumption by disabling unused interfaces.

The current power consumption is approx 7.5W on my carrier board including the verdin module WB/IT module and peripherals.

The unused interfaces are all the display, graphics, camera, hdmi, JTAG, QSPI, CAN, PCIE, ETH2, MSP.

My current overlay is as follows:

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
 * Copyright 2023 Your Company Name
 */

/dts-v1/;
/plugin/;

// #include "device-trees/dts-arm64/imx8mm-verdin.dtsi" // this does not work as somehow the tcb task build cant find it
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/leds/common.h>
#include "imx8mm.dtsi"

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

&{/} {
   codec_ext: max98357a@0 {
      compatible = "maxim,max98357a";
      #sound-dai-cells = <0>;
      clocks = <&clk IMX8MM_CLK_SAI2_ROOT>;
      clock-names = "bclk";
      status = "okay";
   };

   sound {
      compatible = "simple-audio-card";
      status = "okay";
      simple-audio-card,name = "max98357a";

      simple-audio-card,format = "i2s";
      simple-audio-card,bitclock-master = <&dailink_master_cpu>;
      simple-audio-card,frame-master = <&dailink_master_cpu>;

      dailink_master: simple-audio-card,codec {
         sound-dai = <&codec_ext>;
         clocks = <&clk IMX8MM_CLK_SAI2_ROOT>;
      };

      dailink_master_cpu: simple-audio-card,cpu {
         sound-dai = <&sai2>;
      };
   };
};

/* Disable gpu */
&gpu {
   status = "disabled";
};

/* Disable display subsystem */
&{/soc@0/bus@32c00000/display-subsystem} {
   status = "disabled";
};

/* Disable lcd-if */
&lcdif {
   status = "disabled";
};

/* Disable mipi-dsi */
&mipi_dsi {
   status = "disabled";
};

/* Disable mipi-csi */
&csi1_bridge {
   status = "disabled";
};

/* Disable mipi-csi */
&mipi_csi_1 {
   status = "disabled";
};

/* Verdin I2S_1 */
&sai2 {
   assigned-clock-rates = <11289600>;
   status = "okay";
};

/* Verdin SD_1 */
&usdhc2 {
   status = "okay";
};

/* Enable the Ethernet PHY */
&fec1 {
   status = "okay";
};

/* Verdin I2C_1 */
&i2c4 {
   #address-cells = <1>;
   #size-cells = <0>;
   status = "okay";

   // disable the toradex pca953x gpio expander
   gpio_expander_21: gpio-expander@21 {
      status = "disabled";
   };

   /* GPIO EXPANDER AT 0x21
   STATUS: DETECTED AND DRIVER LOADING
    */
   gpio_exp_cb: gpio_exp_cb@21 {
      compatible = "nxp,pcal6416";
      #gpio-cells = <2>;
      gpio-controller;
      interrupt-parent = <&gpio1>; /* gpio1 contains SODIMM_216 (named gpio5 in schematics) */
      interrupts = <0 IRQ_TYPE_EDGE_FALLING>; /* gpio1_216 */
      interrupt-controller; // this is a interrupt controller
      interrupt-cells = <2>;
      reg = <0x21>;
      status = "okay";


   };

   /* LSM6 IMU AT 0x6a
   STATUS: DETECTED AND DRIVER LOADING
    */
   lsm6_imu: imu@6a {
      compatible = "st,lsm6dsl";
      reg = <0x6a>;
      status = "okay";
      interrupt-parent = <&gpio_exp_cb>;
      interrupts = <9 IRQ_TYPE_EDGE_FALLING>, <10 IRQ_TYPE_EDGE_FALLING>; // INT1 on pin 9 (504), INT2 on pin 10 (505)
      cs-gpios = <&gpio_exp_cb 8 GPIO_ACTIVE_HIGH>; // CS on pin 8 (503)
      st,intpin = <1>; // 1: INT1, 2: INT2
   };

   /* No nuvoton nau8822 in SOMV3 */
   nau8822_1a: audio-codec@1a {
      compatible = "nuvoton,nau8822";
      reg = <0x1a>;
      status = "disabled";
   };
   // codec@1a {
      //    compatible = "nuvoton,nau8822";
      //    reg = <0x1a>;
      //    status = "disabled";
   // };
   // /delete-node/ codec@1a;

   /* example taken from https: //forums.raspberrypi.com/viewtopic.php?t=243562#p1640265 */
   /* another example https: //android.googlesource.com/kernel/msm/+/refs/tags/android-s-beta-5_r0.4/arch/arm64/boot/dts/google/sm7150-sunfish-pac193x.dtsi */
   /* PAC1934 POWER MONITOR AT REG 0x18
   STATUS: DETECTED AND DRIVER LOADING
    */
   pac1934@18 {
      compatible = "microchip,pac1934";
      reg = <0x18>;
      samp-rate = <64>;
      status = "okay";

      // /* CHANNEL 1 (0) IS CONNECTED TO BATTERY FOR CURRENT MEASUREMENT */
      // ch1: channel@0 {
         //    bi-dir;
         //    uohms-shunt-res = <50000>; /* shunt resistor is 50 milliohm */
         //    rail-name = "BAT";
         //    subsys-name = "SUBSYS_BAT";
         //    channel_enabled;
      // };

      // /* CHANNEL 2 (1) IS CONNECTED TO VBUS_CHG FOR VOLTAGE MEAS ONLY */
      // ch2: channel@1 {
         //    /* uni-directional channel because of missing "bi-dir" property */
         //    bi-dir;
         //    uohms-shunt-res = <0>; /* shunt resistor is not present */
         //    rail-name = "VBUS";
         //    subsys-name = "SUBSYS_VBUS";
         //    channel_enabled;
      // };

      // /* CHANNEL 3 (2) IS CONNECTED TO SYS_PWR FOR CURRENT MEASUREMENT */
      // ch3: channel@2 {
         //    bi-dir;
         //    uohms-shunt-res = <50000>; /* shunt resistor is 50 milliohm */
         //    rail-name = "SYS";
         //    subsys-name = "SUBSYS_SYS";
         //    channel_enabled;
      // };

      // /* CHANNEL 4 (3) IS CONNECTED TO MEASURE SOM SUPPLY VOLTAGE ONLY */
      // ch4: channel@3 {
         //    bi-dir;
         //    uohms-shunt-res = <0>; /* shunt resistor is not present */
         //    rail-name = "5V_SOM";
         //    subsys-name = "SUBSYS_SOM";
         //    channel_enabled;
      // };

      channel@1 {
         reg = <0x1>;
         shunt-resistor-micro-ohms = <50000>;
         label = "BAT";
         bipolar;
      };

      channel@2 {
         reg = <0x2>;
         shunt-resistor-micro-ohms = <0>;
         label = "VBUS";
      };

      channel@3 {
         reg = <0x3>;
         shunt-resistor-micro-ohms = <50000>;
         label = "SYS";
         bipolar;
      };

      channel@4 {
         reg = <0x4>;
         shunt-resistor-micro-ohms = <0>;
         label = "SOM";
      };
   };

   /* PCA9633 LED DRIVER AT REG 0x61
   STATUS: DETECTED AND DRIVER LOADING
    */
   pca9633@61 {
      compatible = "nxp,pca9633";
      reg = <0x61>;
      #address-cells = <1>;
      #size-cells = <0>;
      status = "okay";

      lidar@0 {
         label = "lidar";
         reg = <0>;
         linux,default-trigger = "none";
      };
      unused1@1 {
         label = "pwm_empty1";
         reg = <1>;
         linux,default-trigger = "none";
      };
      unused2@2 {
         label = "pwm_empty2";
         reg = <2>;
         linux,default-trigger = "none";
      };
      unused3@3 {
         label = "pwm_empty3";
         reg = <3>;
         linux,default-trigger = "none";
      };
   };


   /*
   https: //lore.kernel.org/linux-pm/20201009121532.GN1042@kadam/t/
   https: //www.mail-archive.com/linux-kernel@vger.kernel.org/msg2254373.html
    */
   bat: battery {
      compatible = "simple-battery";
      constant-charge-current-max-microamp = <2000000>;
      constant-charge-voltage-max-microvolt = <4200000>;
      precharge-current-microamp = <160000>;
      charge-term-current-microamp = <1500000>;
   };
   bq25790: charger@6b {
      compatible = "ti,bq25792";
      reg = <0x6b>;
      interrupt-parent = <&gpio1>; // gpiochip0 contains SODIMM_218 which is gpio no 11 of gpiochip0
      interrupts = <11 IRQ_TYPE_EDGE_FALLING>; // gpiochip0 gpio 11 is SODIMM_218
      ti,watchdog-timeout-ms = <2000>;
      input-current-limit-microamp = <1500000>;
      input-voltage-limit-microvolt = <4500000>;
      monitored-battery = <&bat>;
   };

   /* LED DRIVER LP55231 AT REG 0x32
   STATUS: DETECTED ON I2C BUS BUT DRIVER NOT LOADING
    */
   lp55231: led@32 {
      compatible = "ti,lp5523";
      reg = <0x32>;
      status = "okay";
      clock-mode = /bits/ 8 <1>; // 1: internal oscillator

      /* first multicolor led */
      multi-led@1 {
         #address-cells = <1>;
         #size-cells = <0>;
         reg = <0x1>;
         color = <LED_COLOR_ID_RGB>;
         function = LED_FUNCTION_STANDBY;
         linux,default-trigger = "heartbeat";

         led@0 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x0>;
            color = <LED_COLOR_ID_GREEN>;
         };

         led@1 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x1>;
            color = <LED_COLOR_ID_BLUE>;
         };

         led@6 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x6>;
            color = <LED_COLOR_ID_RED>;
         };
      };

      /* second multicolor led */
      multi-led@2 {
         #address-cells = <1>;
         #size-cells = <0>;
         reg = <0x2>;
         color = <LED_COLOR_ID_RGB>;
         function = LED_FUNCTION_STANDBY;
         linux,default-trigger = "heartbeat";

         led@2 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x2>;
            color = <LED_COLOR_ID_GREEN>;
         };

         led@3 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x3>;
            color = <LED_COLOR_ID_BLUE>;
         };

         led@7 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x7>;
            color = <LED_COLOR_ID_RED>;
         };
      };

      /* third multicolor led */
      multi-led@3 {
         #address-cells = <1>;
         #size-cells = <0>;
         reg = <0x3>;
         color = <LED_COLOR_ID_RGB>;
         function = LED_FUNCTION_STANDBY;
         linux,default-trigger = "heartbeat";

         led@4 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x4>;
            color = <LED_COLOR_ID_GREEN>;
         };

         led@5 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x5>;
            color = <LED_COLOR_ID_BLUE>;
         };

         led@8 {
            led-cur = /bits/ 8 <50>;
            max-cur = /bits/ 8 <100>;
            reg = <0x8>;
            color = <LED_COLOR_ID_RED>;
         };
      };
   };



};

Any suggestions to reduce power consumption are welcome.

Hi, I’m the Toradex AI Assistant. I’m in early beta, and I would appreciate your feedback.
The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello,

To further reduce power consumption on your Verdin iMX8MM module, considering the interfaces you’ve already disabled, you can take additional steps. Here are some suggestions:

  1. Disable Unused Peripherals in the Device Tree: You’ve disabled a number of interfaces, but ensure that all unused peripherals such as SPI, I2C (if not used), UARTs, and any other interfaces not required for your application are disabled in the device tree. This can be done by setting their status to “disabled”.

  2. Optimize Clock Settings: Review the clock settings for the peripherals you are using. Sometimes, peripherals are configured to run at higher clock speeds than necessary. Reducing the clock speed can save power.

  3. CPU Frequency Scaling: Make sure that the CPU frequency scaling is enabled and properly configured. This allows the CPU to run at a lower frequency when the system is idle or under light load, reducing power consumption.

  4. Power Management IC (PMIC) Configuration: The Verdin iMX8MM module includes a PMIC. Ensure that it’s configured for optimal power saving, taking advantage of its features like Dynamic Voltage Scaling (DVS), which adjusts the voltage based on load.

  5. Review the Power Supply Design: Ensure that your carrier board’s power supply design is efficient and does not contribute to unnecessary power loss. This includes using efficient voltage regulators and minimizing voltage drops.

  6. Software Optimization: Optimize your software to reduce CPU load. This includes optimizing algorithms, reducing unnecessary processing, and using sleep modes effectively.

  7. Use Linux Power Management Features: Linux offers various power management features such as CPUidle, CPUfreq, and Runtime Power Management. Make sure these are enabled and configured to suit your application’s needs.

  8. Disable Ethernet PHY: If you’re not using the second Ethernet interface (ETH2), ensure that the PHY for this interface is disabled. This can be done by setting the status of the PHY node to “disabled” in the device tree.

  9. Disable Wi-Fi and Bluetooth: If your module includes Wi-Fi and Bluetooth and these are not used, ensure they are disabled. This can significantly reduce power consumption.

  10. Review Active Peripherals’ Power Settings: For peripherals that are in use, review their power settings. For example, if I2C is used, consider lowering its clock speed if high speed is not required.

By carefully reviewing each component of your system and ensuring that only necessary components are powered and configured for optimal performance,

Please, also check if these links can help you solve your problem:

How to Write Device Tree Overlays | Toradex Developer Center.

Greetings @geopaxpvtltd,

It seems you’ve already disabled quite a bit of interfaces on the SOM side of things. The only other major thing I can think of would be to tune the CPU power usage as described here: How to Lower CPU Power Consumption | Toradex Developer Center

This of course will have an effect on CPU performance, but you’ll have to weigh that against your requirements.

Do you have a target power consumption you’re aiming for?

Best Regards,
Jeremias

Hi @jeremias.tx !

I have already observed the cpu usage and it mostly runs at 1.2 Ghz as my application is not that cpu intensive.

if I disable one CPU core, how much power do you reckon I will save?

My peripherals are a 1W GPS, a 1W radio and a 1W 4G module along with some other peripherals such as uart and USB hubs, GPIO expanders, pwm controllers and led controllers and an IMU.

If I could somehow bring the consumption down to around 5.5W to 6W, that would be great!

I was unsure of the way I used to disable the peripherals already done; whether it is correct or not.

if I disable one CPU core, how much power do you reckon I will save?

I don’t think I can put a number to this. Best would be to test the effects of it on your use-case with your software to be sure.

If I could somehow bring the consumption down to around 5.5W to 6W, that would be great!

Well looking at the rough numbers we have documented here: Verdin iMX8M Mini Power Consumption | Toradex Developer Center

This should be possible with the SOM on it’s own. However, you have a lot of extra peripherals and hardware on your carrier that is increasing your power consumption.

I was unsure of the way I used to disable the peripherals already done; whether it is correct or not.

As far as I’m aware if the subsystem is disabled in the device tree the software will not try to initialize it, meaning it shouldn’t be running and consuming power I would think.

Best Regards,
Jeremias