AM335x Power Management Standby User's Guide

= Standby Mode =

Standby for AM335x is a inactive (system suspended) power saving mode in which the power savings achieved would be lesser than that achieved through DeepSleep0 mode but with lesser resume latency and additional wake-up sources.

= Linux Implementation =

Linux kernel source available here: Linux-Arago CM3 source along with binary available here: CM3-Arago

The function  in the kernel advertises 'standby' as a mode in   on the target. The actual transition to standby is implemented in  in file. The firmware running on CM3 is enhanced with commands and wake handlers for achieving standby low-power mode. The definition of standby mode implemented is as follows -

Note that this definition may not exactly meet the AM335x Technical Reference Manual definition since it has been modified for better latency vs power savings balance under Linux operating system.

After the system has entered standby, wakeup happens only via MPU_WAKE interrupt to Cortex-M3. Also please note that only GPIO based Wake up is supported in standby mode except few analog devices like, TSC and USB.

Entering Standby Mode
Once a kernel image with the right PM firmware has been compiled and booted up, one can enter standby by executing the following command at the command prompt

echo standby &gt; /sys/power/state

Wakeup Sources

 * Wakeup from a peripheral via GPIO method.

Wakeup from standby mode is supported via GPIO method wherein any IO pad can be configured as GPIO while entering into standby mode and wakeup happens through the GPIO interrupt caused by any activity on the respective pad.

Example: Waking up from UART0 on GP-EVM

To achieve wakeup from standby via GPIO method, run the commands below on the command prompt (the commands to mount debugfs may not be required if your filesystem mounts debugfs at boot).

mkdir -p /debugfs mount -t debugfs debugfs /debugfs cd /debugfs/omap_mux/board/ echo uart0_rxd.gpio1_10=0x27,rising > standby_gpio_pad_conf echo standby > /sys/power/state

The above commands configure UART0 RXD pin as a GPIO by configuring the padconf register and also enables wakeup via this GPIO due to a rising edge trigger. Similarly, wakeup from standby can be achieved from any other peripheral by configuring the corresponding IO pads as GPIO.

Note: User should know the IO pads to be configured and the trigger value to be written to them.

GPIO wakeup
One can wakeup from standby from any of the GPIO lines by pressing any button/key connected to a GPIO line.

USB wakeup
For USB Remote Wakeup, run the commands below before entering into standby mode.

echo enabled &gt; /sys/bus/usb/devices/1-1/power/wakeup echo enabled &gt; /sys/bus/usb/devices/usb1/power/wakeup

For kernel v3.14+, the USB PHY driver should enable wakeup too, using the command below.

echo enabled &gt; /sys/bus/platform/devices/47401b00.usb-phy/power/wakeup

Wakeup from standby can be achieved on a mouse click or keyboard key press.

Note:
 * 1) USB wakeup on connect/disconnect of USB device is not supported, please refer to the "Known Limitations" section below.
 * 2) This feature is currently broken in kernel v4.4. The system would immediately wake up without the usb device sending remote wakeup event.

Touchscreen wakeup
Wakeup from standby mode is possible via internal TSC-ADC module. Pressing the touchscreen will cause a wake-up.

MMC/SD wake
Wakeup from standby happens on insertion/removal of MMC card if "card detect" pin is used. MMC/SD driver in Linux configures the "card detect" pin as GPIO hence this becomes equivalent to a GPIO wakeup.

RTC wakeup
Wakeup from standby mode is possible via rtc module. RTC module can be setup for predefined alarm timeout and the system wakes up from standby after that amount of time.

For RTC Wakeup, use 'rtcwake' command to enter and wakeup from standby.

rtcwake -d [RTC device (rtc/rtc0)] -m [suspend mode (mem/standby)] -s [number of seconds]

To enter standby and wake up after 5 seconds with rtc0 as rtc device, use below command. rtcwake -d /dev/rtc0 -m standby -s 5

DM Timer wakeup
Wakeup from standby can be achieved by configuring any of the DMTimers (1-7) to issue an overflow interrupt or compare interrupt. Below are the steps for timer wakeup with overflow interrupt with Timer7.

Before entering standby:

struct standby_dmtmr_struct { struct omap_dm_timer *stndby_tmr; u32 irq_num; }; standby_dmtmr.stndby_tmr = omap_dm_timer_request_specific(7);
 * Enable the timer module from which wakeup is desired (dmTimer7).
 * Request for a specific timer

standby_dmtmr.irq_num = omap_dm_timer_get_irq(standby_dmtmr.stndby_tmr); retval = request_irq(standby_dmtmr.irq_num,standby_dmtmr_interrupt_handler,IRQF_DISABLED,"pm_standby", &standby_dmtmr);
 * Get irq number and register an interrupt handler for this irq

omap_dm_timer_write_status(standby_dmtmr.stndby_tmr,OMAP_TIMER_INT_OVERFLOW);
 * Clear any pending events by writing to the Status Register

omap_dm_timer_set_int_enable(standby_dmtmr.stndby_tmr,OMAP_TIMER_INT_OVERFLOW);
 * Enable overflow interrupt

omap_dm_timer_set_load_start(standby_dmtmr.stndby_tmr, 0,0xF8D8A6FC); Note: With the above value loaded into the counter register, on entering standby, wakeup happens after a duration of 5sec.
 * Load the counter register and start the timer

The value to load can be calculated as follows :
 * 1) Timer Input clk(f) = 24MHz. Hence Time period(T = 1/f) = 1 tick = 41.66 ns
 * 2) 15 seconds = 0.360057 x 10^9 ticks = 0x15760B09
 * 3) Hence timer counter value for 15s overflow is Overflow value - 0x15760B09 = 0xFFFFFFFF - 0x15760B09 = 0xEA89F4F6

While resuming from standby, the below steps needs to be done omap_dm_timer_stop(standby_dmtmr.stndby_tmr); omap_dm_timer_set_int_enable(standby_dmtmr.stndby_tmr, 0); omap_dm_timer_disable(standby_dmtmr.stndby_tmr); omap_dm_timer_free(standby_dmtmr.stndby_tmr); free_irq(standby_dmtmr.irq_num, &standby_dmtmr);
 * Stop the timer
 * Disable the interrupt
 * Disable the timer
 * Free acquired the timer
 * Free the irq
 * Disable clock to the timer module

Refer this patch for dmTimer wakeup from standby.

A Successful Resume Cycle
A successful standby-resume cycle produces console logs as below:

root@arago-armv7:~# echo standby &gt; /sys/power/state [ 3832.488067] PM: Syncing filesystems ... done. [ 3832.499023] Freezing user space processes ... (elapsed 0.01 seconds) done. [ 3832.519226] Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done. [ 3832.539245] Suspending console(s) (use no_console_suspend to debug) [ 3832.574401] PM: suspend of devices complete after 27.770 msecs [ 3832.576080] PM: late suspend of devices complete after 1.617 msecs [ 3833.821868] GFX domain entered low power state [ 3833.821990] Successfully transitioned all domains to low power state [ 3834.033081] PM: early resume of devices complete after 210.601 msecs [ 3834.238708] net eth0: CPSW phy found : id is : 0x4dd074 [ 3834.241394] PM: resume of devices complete after 207.599 msecs [ 3834.284515] Restarting tasks ... done.

= Latency Profiling =


 * Profiling using Timer:

Latency profiling through timer is done by reading the timer1 count register at predefined points in the suspend/resume sequence. Here are the latency values observed through this method.

This patch was used to arrive at the above latency numbers.

Latency profiling using GPIO is done by toggling GPIO(0,31)at the desired points. The pulse resulting from GPIO toggling can be captured on an oscilloscope by monitoring J4,21 on EVM1.1 or EVM1.2a. Here are the latency values observed though this method.
 * Profiling using GPIO:

This patch was used to arrive at the above latency numbers.

= Power Measurements =

Please refer to the Features_and_Performance_Guide [TBD]

= Known Limitations =


 * USB insertion /removal wakeup is supported for standby. USB connect-disconnect wakeup cannot happen via MPU_WAKE it happens only via PHY_WAKE. However, wakeup from standby is supported only through MPU_WAKE. Thus only remote wakeup is possible. Wakeup from standby happens on a mouse click or keyboard press but not on insertion/removal of mouse.


 * Ethernet wakeup for standby is not validated, as on EVM ETH PHY_WAKEUP pin is not hooked up to any GPIO pin.