Linux PM: OMAP3 Suspend Support

This article provides an overview of the Linux kernel support for the suspend state in the TI OMAP3.  Power management has always been one of the more difficult parts of a system to get right.  The OMAP3 power management is quite extensive.  There are many levels of very granular control over the entire system.  Initially, we are going to focus on a simple power state where we want to put the CPU in a low power mode (basically not doing anything), but resume very quickly once an event occurs and continue running applications where they left off.  This is typically called “Suspend”.

Power States

We must first match up terminology between the Linux kernel and the OMAP documentation.  The Linux kernel supports several suspend power states:

  • PM_SUSPEND_ON: system is running
  • PM_SUSPEND_STANDBY: system is in a standby state.  This is typically implemented where the CPU is in a somewhat static state.  After all the peripherals have been shut down, and the memory put into self refresh, the CPU executes an instruction that puts the CPU into a low power state.  After the next wake-event occurs, the CPU resumes operating at the next instruction.  The CPU state is static in this case.
  • PM_SUSPEND_MEM: This goes one step beyond STANDBY in that the CPU is completely powered down and loses its state.  Any CPU state that needs to be saved is stored to SDRAM (which is in self refresh), or some other static memory.  When the system resumes, it has to boot through the reset vector.  The bootloader determines that the system was sleeping, and re-initializes the system, enables the SDRAM, restores whatever state is needed, and then jumps to a vector in the kernel to finish the resume sequence.  This mode is fairly difficult to implement as it involves the bootloader, and a lot of complex initialization code that is difficult to debug.
  • PM_SUSPEND_MAX: From browsing the kernel source code, it appears this state is used for “Off” or perhaps suspend to disk.

The OMAP3 documentation uses the following terms:

  • SLM: Static Leakage Management.  Includes “suspend” functionality.
  • Standby:  OMAP3x retains internal memory and logic.  (uses 7mW)
  • Device Off: System state is saved to external memory(0.590mW).  This could theoretically map to the PM_SUSPEND_MEM state.
  • WFI: Wait for Interrupt.  This is an ARM instruction that puts the CPU in the standby state.

Based on the source code in the Linux kernel, there is currently only support for the Standby state:

static int omap3_pm_enter(suspend_state_t unused)
	int ret = 0;

	switch (suspend_state) {
		ret = omap3_pm_suspend();
		ret = -EINVAL;

	return ret;

What kernel branches/versions support PM

Kevin Hilman has been maintaining an OMAP3 power management branch at  Bits are being merged upstream.  Some of the things that don’t seem to be merged yet are SmartReflex support, and a number of other details.  But, it seems that basic suspend/resume support is available in the upcoming 2.6.32 kernel.

More Details on the Standby Mechanism

Due to the granularity and complexity of the the OMAP3 power management, relevant pieces of documentation are scattered throughout the OMAP35x Technical Reference Manual.  The following were helpful:

  • Table 3-17: details the MPU subsystem operation power modes
  • Table 3-18: Power Mode Allowable Transitions.  Standby
    mode can enter from active mode only by executing the wait for interruption (WFI) instruction.
  • SDRC, “Self Refresh Management”.  The OMAP3 can automatically put the SDRAM in self refresh mode when the CPU enters the idle state.
  • MPU Power Mode Transistions: The ARM core initiates entering into standby via software only (CP15 – WFI).

The omap34xx_cpu_suspend function is called to put the CPU into standby mode.  The actual instruction that stops the CPU is the ARM WFI (wait for interrupt) instruction.  This is a little different than previous generations of ARM CPUs that used coprocessor registers.


With the 2.6.32-rcX kernels, suspend/resume appears to work at least from the console:

root@overo:~# echo mem > /sys/power/state
PM: Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.00 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.
Suspending console(s) (use no_console_suspend to debug)

<after key press on serial console ...>

omapfb omapfb: timeout waiting for FRAME DONE
CLIFF: going into suspend
Wake up daisy chain activation failed.
CLIFF: returning from suspend
Successfully put all powerdomains to target state
Restarting tasks ...

The CLIFF messages are debug statements placed in the low-level suspend code to make sure we were getting to that point.  The console is disabled early in the suspend process, so we don’t get the debug messages until after resume.  The no_console_suspend kernel option can be used to leave the console enabled during suspend, but that feature does not seem to work.

Summary/Future work

This covers the basics of Linux Suspend/Resume support for the OMAP3 CPU.  There are many more options and details such as configuring wake sources, dynamic power management while running, etc.