3.2.2.11.6. Wakeup Sources

This section talks about the multiple ways in which we can wakeup the AM62x SoC from Low Power modes like Deep Sleep or MCU only. The AM62x SoC support various wakeup sources like GP Timers, RTC Timer, UART, I2C, WKUP GPIO, and I/O Daisy Chain.

The following wakeup sources are supported in this SDK release:

  1. Real-Time Clock (RTC)

  2. MCU (WKUP) GPIO

  3. Main I/O Daisy Chain (Main GPIO and Main UART)

  4. USB Wakeup

  5. MCU IPC (for MCU Only mode)

  6. CAN UART (for Partial I/O mode)

3.2.2.11.6.1. Real-Time Clock (RTC)

It’s possible to use the SoC’s internal RTC to wakeup the system using the command rtcwake:

rtcwake

- Show whether an alarm is set or not:
    rtcwake -m show -v

- Suspend to RAM and wakeup after 10 seconds:
    rtcwake -m mem -s {{10}}

- Suspend to disk (higher power saving) and wakeup 15 minutes later:
    rtcwake -m disk --date +{{15}}min

- Freeze the system (more efficient than suspend-to-RAM but version 3.9 or newer of the Linux kernel is required) and wakeup at a given date and time:
    rtcwake -m freeze --date {{YYYYMMDDhhmm}}

- Disable a previously set alarm:
    rtcwake -m disable

- Perform a dry run to wakeup the computer at a given time. (Press Ctrl + C to abort):
    rtcwake -m on --date {{hh:ss}}

For example, if you wish to wakeup from Deep Sleep or MCU Only mode in 10 seconds, use the command like this:

root@am62xx-evm:~# rtcwake -s 10 -m mem
rtcwake: wakeup from "mem" using /dev/rtc0 at Thu Apr 28 18:05:07 2022
[  217.136973] PM: suspend entry (deep)
[  217.140747] Filesystems sync: 0.000 seconds
[  217.147762] Freezing user space processes
[  217.153867] Freezing user space processes completed (elapsed 0.002 seconds)
[  217.160915] OOM killer disabled.
[  217.164149] Freezing remaining freezable tasks
[  217.170101] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[  217.177507] printk: Suspending console(s) (use no_console_suspend to debug)
[  217.430054] Disabling non-boot CPUs ...
[  217.432261] psci: CPU1 killed (polled 0 ms)
[  217.435103] psci: CPU2 killed (polled 0 ms)
[  217.437754] psci: CPU3 killed (polled 0 ms)
[  217.438625] Enabling non-boot CPUs ...
[  217.439024] Detected VIPT I-cache on CPU1
[  217.439117] GICv3: CPU1: found redistributor 1 region 0:0x00000000018a0000
[  217.439182] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[  217.440126] CPU1 is up
[  217.440374] Detected VIPT I-cache on CPU2
[  217.440419] GICv3: CPU2: found redistributor 2 region 0:0x00000000018c0000
[  217.440461] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
[  217.441134] CPU2 is up
[  217.441392] Detected VIPT I-cache on CPU3
[  217.441442] GICv3: CPU3: found redistributor 3 region 0:0x00000000018e0000
[  217.441486] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
[  217.442257] CPU3 is up
[  217.442874] ti-sci 44043000.system-controller: ti_sci_resume: wakeup source: 0x50
[  217.454117] am65-cpsw-nuss 8000000.ethernet: set new flow-id-base 19
[  217.463141] am65-cpsw-nuss 8000000.ethernet eth0: PHY [8000f00.mdio:00] driver [TI DP83867] (irq=POLL)
[  217.463172] am65-cpsw-nuss 8000000.ethernet eth0: configuring for phy/rgmii-rxid link mode
[  217.469924] am65-cpsw-nuss 8000000.ethernet eth1: PHY [8000f00.mdio:01] driver [TI DP83867] (irq=POLL)
[  217.469938] am65-cpsw-nuss 8000000.ethernet eth1: configuring for phy/rgmii-rxid link mode
[  217.728474] OOM killer enabled.
[  217.731625] Restarting tasks ... done.
[  217.737936] random: crng reseeded on system resumption
[  217.743270] k3-m4-rproc 5000000.m4fss: received echo reply from 5000000.m4fss
[  217.751165] PM: suspend exit
root@am62xx-evm:~#

3.2.2.11.6.2. MCU GPIO

One of the most common ways to wakeup a system is by using some I/O activity. MCU GPIOs allow us to do this by configuring the MCU GPIO controller as a wakeup source. In ideal scenarios, The firmware running on MCU core is responsible for configuring MCU GPIO’s as a wakeup source. However, if the application design doesn’t rely too much on the MCU firmware then linux can be used to configure the MCU GPIOs as a wakeup source. You can refer to the mcu_gpio_key node in k3-am62x-sk-lpm-wkup-sources.dtso and use it as a template to configure the MCU GPIO of your choice as a wakeup capable GPIO.

A brief guide to configuring an MCU GPIO as wakeup:

First, we add gpio-keys as a compatible string, refer to gpio_keys kernel documentation for details.

compatible = "gpio-keys";

Set the desired pinctrl,

pinctrl-names = "default";
pinctrl-0 = <&wake_mcugpio1_pins_default>;

Setup the interrupt parent and interrupt as MCU_GPIO0,

interrupt-parent = <&mcu_gpio0>;
interrupts = <16 IRQ_TYPE_EDGE_RISING>;

Now, under the switch node we add the following:

switch {
            label = "MCUGPIO";
            linux,code = <143>;
            gpios = <&mcu_gpio0 16 GPIO_ACTIVE_LOW>;
            wakeup-source;
};
  1. The label is the descriptive name of the key. The string will reflect under /proc/interrupts as:

    root@evm:~# cat /proc/interrupts | grep "MCUGPIO"
    262:          0          0          0          0      GPIO  16 Edge    -davinci_gpio  MCUGPIO
    
  2. linux,code: Keycode to emit.

  3. gpios: the gpio required to be used as the gpio-key.

  4. The wakeup-source property describes devices which have wakeup capability.

This indicates that gpio_keys can wake-up the system from Deep Sleep or MCU Only mode.

The reason we can easily use MCU GPIOs to wakeup the system from deep sleep is because MCU GPIO’s are in a power domain that is never really shut down. This means that this domain stays ON even when the SOC is in deep sleep. Hence, the GPIO controller is able to act as a wakeup source and send a wakeup interrupt to the Device Manager. To understand the role of Device Manager please refer to S/W Architecture of System Suspend

MCU GPIO wakeup can only be tested when k3-am62x-sk-lpm-wkup-sources.dtso overlay is loaded. Please refer to How to enable DT overlays for more details.

Once the system has entered Deep Sleep or MCU Only mode as shown in the LPM section, wakeup from MCU GPIO0_16 can be triggered by grounding Pin 11 on J8 MCU Header.

3.2.2.11.6.3. Main I/O Daisy Chain

The main domain is powered-off when the SoC enters low power mode. This includes controllers like Main UART, GPIO, I2C, etc. The question then arises how to wakeup the SoC from peripherals connected to these controllers (for example main UART)? Here’s where the role of I/O Daisy Chaining comes in. At the hardware level, all the pads in an SoC have to be pinmuxed to dedicated controllers like UART or GPIO.

For example, If a key press on Main UART (which is used for linux console logs) were to wakeup the system from deep sleep then simply configuring the Main UART controller as a wakeup source wouldn’t suffice. This is because the UART controller is powered off and wouldn’t be able to register any key press as such. However, at the “pad” level we are still connected, and the pads have a specific way to be configured as wakeup sources.

For detailed information and sequence please refer to I/O Power Management and Daisy Chaining section in the TRM. To briefly explain, Setting the 29th Bit in the desired padconfig register, allows the pad to act as a wakeup source by triggering a wake irq to the DM R5 in deep sleep states.

Note

AM62x supports the ability to wakeup using pad based wake event ONLY in Deep Sleep or MCU Only Mode. During active system usage, even if the wake_enable bit is set the system will be unresponsive to any wakeup activity on that pad.

To demonstrate I/O daisy chain wakeup as part of AM62x offering, two reference examples are provided:

  1. main_uart0 is used where a key press on the linux console can wakeup the system.

  2. main_gpio is used where activity on configured GPIO pin can wakeup the system.

3.2.2.11.6.3.1. Main UART

The way to configure UART as an I/O daisy chain wakeup, refer to the main_uart0 node in k3-am62x-sk-common.dtsi

interrupts-extended = <&gic500 GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
            <&main_pmx0 0x1c8>; /* (D14) UART0_RXD PADCONFIG114 */
interrupt-names = "irq", "wakeup";

Here, we chain the IRQ to the pinctrl driver using the second interrupts-extended entry. The wake IRQ framework in linux works in such a way that the second entry gets marked as a wakeup source, and then the pinctrl driver is informed that the pad 0x1c8 in this case is to be configured as a wakeup pad when system enters deep sleep.

To use main_uart0 as a wakeup source, ensure serial is a wake-irq in /proc/interrupts:

root@evm:~# grep wakeup /proc/interrupts
231:          0          0          0          0   pinctrl 456 Edge 2800000.serial:wakeup

Then, run this script:

#!/bin/bash -xe

# Detach kernel serial console
consoles=$(find /sys/bus/platform/devices/*.serial/ -name console)
for console in ${consoles}; do
        echo -n N > ${console}
done

# Configure PM runtime autosuspend
uarts=$(find /sys/bus/platform/devices/*.serial/power/ -type d)
for uart in $uarts; do
        echo -n 3000 > $uart/autosuspend_delay_ms
        echo -n enabled > $uart/wakeup
        echo -n auto > $uart/control
done

# Configure wake-up from suspend
uarts=$(find /sys/class/tty/tty[SO]*/power/ -type d 2>/dev/null)
for uart in $uarts; do
        echo -n enabled > $uart/wakeup
done

This will configure UART to act as deep sleep wakeup source, and then a key press on same terminal should trigger a wakeup from deep sleep.

Any other pad can be chosen as per application requirements depending on which pad is required to wakeup the system.

3.2.2.11.6.3.2. Main GPIO

Configuring Main GPIO as an I/O daisy chain wakeup source requires a combination of gpio-keys with chained IRQ in the pinctrl driver. The configuration and working of these frameworks have been covered under the MCU GPIO and Main UART sections.

The reference configuration for Main GPIO wakeup can be found under gpio_key node in k3-am62x-sk-lpm-wkup-sources.dtso

Main GPIO wakeup can only be tested when k3-am62x-sk-lpm-wkup-sources.dtso overlay is loaded. Please refer to How to enable DT overlays for more details.

To use main_gpio as a wakeup source, ensure gpio is a wake-irq in /proc/interrupts:

root@evm:~# grep wakeup /proc/interrupts
531:          0          0          0          0   pinctrl 416 Edge      WKGPIO:wakeup

Once the system has entered Deep Sleep or MCU Only mode as shown in the LPM section, wakeup from MAIN GPIO1_10 can be triggered by grounding Pin 33 on J3 User Expansion Connector.

3.2.2.11.6.4. USB Wakeup methods

System wakeup is possible through the USB events in both Host and Device mode.

3.2.2.11.6.4.1. Host Mode Wakeup Events

The USB wakeup events in Host mode are described below:

3.2.2.11.6.4.1.1. Wakeup via a device connect event

Follow the steps described in LPM section to put the system in Low Power Mode via Deep Sleep or MCU only method.

Now plug in a USB device to one of the port on the board and the system should wakeup. Post wakeup, the device would show up enumerated. This can be checked by below command before and after suspending and waking up the system.

# lsusb -t

3.2.2.11.6.4.1.2. Wakeup via a device disconnect event

Plug in a USB device to one of the port on the board and check that the device is enumerated by executing the below command.

# lsusb -t

Follow the steps described in LPM section to put the system in Low Power Mode via Deep Sleep or MCU only method.

Once the system is suspended, disconnect the USB device from the board and this should wakeup the system. And device would not show up in list of USB enumerated devices. This can be verified by executing

# lsusb -t

3.2.2.11.6.4.1.3. Via Remote wakeup event

Use a device that supports USB suspend/resume and ensure that the USB device can suspend and resume correctly. For a example a Logitech USB keyboard that supports suspend/resume. Follow below steps to check whether the keyboard is capable to trigger a remote wakeup event to system.

Assuming the USB keyboard device is at /sys/bus/usb/devices/1-1/, enable USB autosuspend and wakeup

# echo auto > /sys/bus/usb/devices/1-1/power/control
# echo enabled > /sys/bus/usb/devices/1-1/power/wakeup

Allow for two seconds of inactivity and check the runtime power status of the keyboard. It should show “suspended”, indicating that the keyboard has entered into suspend state.

# cat /sys/bus/usb/devices/1-1/power/runtime_status

Now press a key on the keyboard and check the runtime power status and it would come back to “active”.

# cat /sys/bus/usb/devices/1-1/power/runtime_status

Follow the steps described in LPM section to put the system in Low Power Mode via Deep Sleep or MCU only method.

And once in suspended state, trigger system wakeup via remote wakeup event by typing keys on the keyboard. The system would wakeup. And USB keyboard would still be present in the system’s list of USB enumerated devices and this can be verified by executing

# lsusb -t

3.2.2.11.6.4.2. Device Mode Wakeup Events

3.2.2.11.6.4.2.1. Wakeup via connect event

Load a USB gadget driver such as g_zero

# modprobe g_zero

Follow the steps described in LPM section to put the system in Low Power Mode via Deep Sleep or MCU only method.

Once the system has entered the suspend state, plug a cable from a different Host system to the board’s USB DRP port. This should wakeup the system and gadget would be enumerated on the Host. Enumeration of the gadget on the Host system can be verified by executing the below command on the Host system

HOST:~$ > lsub -t

3.2.2.11.6.5. MCU IPC based Wakeup

It’s possible to use IPC based wakeup events from the MCU core. For details on how to implement this from the firmware side, please refer to the relevant documentation:

MCU+ SDK for AM62x

To use MCU IPC based wakeup, system should be placed into MCU Only mode as shown in the LPM section.

Once the SoC enters MCU Only mode, the following log should be printed on the MCU UART (in most cases it will be /dev/ttyUSB3)

[IPC RPMSG ECHO] Suspend request to MCU-only mode received
[IPC RPMSG ECHO] Press any key on this terminal to resume the kernel from MCU only mode

Any key press on the same terminal should trigger a wakeup from MCU Only mode and the following message printed:

[IPC RPMSG ECHO] Main domain resumed due to MCU UART

3.2.2.11.6.6. Confirming the Wakeup event type

When the SoC wakes up from any Low Power Mode, the Device Manager logs the wake reason. This wake reason can be queried by Linux using the TISCI LPM API.

This wake reason is printed as part of the Linux suspend/resume log:

[   37.357109] CPU3 is up
[   37.357710] ti-sci 44043000.system-controller: ti_sci_resume: wakeup source: 0x50

In the above example, 0x50 means that WKUP_RTC0 is the wakeup source.