3.3.6. Wakeup Sources
This section talks about the multiple ways in which we can wakeup the AM62x SoC from various low power modes. The AM62x SoC support various wakeup sources like GP Timers, RTC Timer, UART, I2C, WKUP GPIO, and I/O Daisy Chain.
The table below lists the wakeup sources supported in this SDK release and whether that source is valid for given low power modes:
Wakeup Source |
Deep Sleep |
MCU Only |
Partial I/O |
|---|---|---|---|
Real-Time Clock (RTC) |
Yes |
Yes |
No |
MCU (WKUP) GPIO |
Yes |
Yes |
No |
Main I/O Daisy Chain (Main GPIO and Main UART) |
Yes |
Yes |
No |
USB Wakeup |
Yes |
Yes |
No |
WKUP UART |
Yes |
Yes |
No |
MCU IPC (for MCU Only mode) |
No |
Yes |
No |
CAN UART I/O Daisy Chain |
Yes |
Yes |
Yes |
3.3.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}}
- 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, to wakeup from Deep Sleep in 10 seconds, use the command like this:
Note
An additional -d rtc1 option is required on BeaglePlay as the SoC’s
internal RTC gets probed as rtc1
root@am62xx-evm:~# rtcwake -s 10 -m mem
rtcwake: wakeup from "mem" using /dev/rtc0 at Thu Jan 1 00:00:45 1970
[ 28.038332] PM: suspend entry (deep)
[ 28.042057] Filesystems sync: 0.000 seconds
[ 28.050312] Freezing user space processes
[ 28.052137] Freezing user space processes completed (elapsed 0.001 seconds)
[ 28.052162] OOM killer disabled.
[ 28.052166] Freezing remaining freezable tasks
[ 28.053557] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 28.053571] printk: Suspending console(s) (use no_console_suspend to debug)
[ 28.138190] ti-sci 44043000.system-controller: ti_sci_cmd_set_device_constraint: device: 179: state: 1: ret 0
[ 28.148680] ti-sci 44043000.system-controller: ti_sci_cmd_set_device_constraint: device: 178: state: 1: ret 0
[ 29.911265] omap8250 2800000.serial: PM domain pd:146 will not be powered off
[ 29.923288] ti-sci 44043000.system-controller: ti_sci_cmd_set_device_constraint: device: 117: state: 1: ret 0
[ 30.789584] remoteproc remoteproc0: stopped remote processor 5000000.m4fss
[ 30.981215] Disabling non-boot CPUs ...
[ 30.983394] psci: CPU1 killed (polled 0 ms)
[ 30.986714] psci: CPU2 killed (polled 0 ms)
[ 30.990028] psci: CPU3 killed (polled 0 ms)
[ 30.991437] Enabling non-boot CPUs ...
[ 31.011850] Detected VIPT I-cache on CPU1
[ 31.011909] GICv3: CPU1: found redistributor 1 region 0:0x00000000018a0000
[ 31.011972] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[ 31.013028] CPU1 is up
[ 31.033291] Detected VIPT I-cache on CPU2
[ 31.033322] GICv3: CPU2: found redistributor 2 region 0:0x00000000018c0000
[ 31.033365] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
[ 31.034221] CPU2 is up
[ 31.054487] Detected VIPT I-cache on CPU3
[ 31.054524] GICv3: CPU3: found redistributor 3 region 0:0x00000000018e0000
[ 31.054573] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
[ 31.055431] CPU3 is up
[ 31.058242] ti-sci 44043000.system-controller: ti_sci_resume: wakeup source: 0x50
[ 33.771971] am65-cpsw-nuss 8000000.ethernet: set new flow-id-base 19
[ 34.177716] am65-cpsw-nuss 8000000.ethernet eth0: PHY [8000f00.mdio:00] driver [TI DP83867] (irq=POLL)
[ 34.177741] am65-cpsw-nuss 8000000.ethernet eth0: configuring for phy/rgmii-rxid link mode
[ 34.184415] am65-cpsw-nuss 8000000.ethernet eth1: PHY [8000f00.mdio:01] driver [TI DP83867] (irq=POLL)
[ 34.184425] am65-cpsw-nuss 8000000.ethernet eth1: configuring for phy/rgmii-rxid link mode
[ 34.400791] OOM killer enabled.
[ 34.403934] Restarting tasks ... done.
[ 34.408982] random: crng reseeded on system resumption
[ 34.555214] k3-m4-rproc 5000000.m4fss: Core is off in resume
[ 34.560924] remoteproc remoteproc0: powering up 5000000.m4fss
[ 34.566695] remoteproc remoteproc0: Booting fw image am62-mcu-m4f0_0-fw, size 55016
[ 34.595350] rproc-virtio rproc-virtio.2.auto: assigned reserved memory node m4f-dma-memory@9cb00000
[ 34.605831] virtio_rpmsg_bus virtio1: rpmsg host is online
[ 34.611540] rproc-virtio rproc-virtio.2.auto: registered virtio1 (type 7)
[ 34.618396] remoteproc remoteproc0: remote processor 5000000.m4fss is now up
[ 34.619659] virtio_rpmsg_bus virtio1: creating channel ti.ipc4.ping-pong addr 0xd
[ 34.633257] virtio_rpmsg_bus virtio1: creating channel rpmsg_chrdev addr 0xe
[ 34.645777] PM: suspend exit
root@am62xx-evm:~#
Note
The system will enter the mode selected by DM on the basis on existing constraints.
3.3.6.2. MCU GPIO
One of the most common ways to wakeup a system is by using some I/O activity.
I/O activity on the MCU GPIOs can wakeup the system when the MCU GPIO
controller is configured as a wakeup source. In ideal scenarios, the firmware
running on MCU core is responsible for configuring MCU GPIOs as a wakeup
source. However, if the application design doesn’t rely on the MCU firmware
then Linux can be used to configure the MCU GPIOs as a wakeup source. Refer
to the mcu_gpio_key node in
k3-am62x-sk-lpm-wkup-sources.dtso
to use as a template to configure the desired MCU GPIO as a wakeup capable
GPIO.
A brief guide to configuring an MCU GPIO as wakeup:
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 as MCU_GPIO0, then setup the interrupt.
interrupt-parent = <&mcu_gpio0>; interrupts = <4 IRQ_TYPE_EDGE_RISING>;
Create following child node as a
switchnode:switch { label = "MCUGPIO"; linux,code = <143>; gpios = <&mcu_gpio0 4 GPIO_ACTIVE_LOW>; wakeup-source; };
label: Descriptive name of the switch node. If the MCU GPIO node is setup correctly, the label will appear under
/proc/interrupts.linux,code: Keycode to emit.
gpios: The GPIO required to be used as the gpio-key.
wakeup-source: wakeup-source property describes devices which have wakeup capability.
To confirm that gpio_keys can wakeup the system from Deep Sleep or MCU Only mode, check
/proc/interruptsfor the label:root@<machine>:~# cat /proc/interrupts | grep "MCUGPIO" 273: 0 0 0 0 GPIO 4 Edge -davinci_gpio MCUGPIO
This indicates that gpio_keys can wake-up the system from Deep Sleep or MCU Only mode.
The MCU GPIOs can be used to wakeup the system from Deep Sleep because MCU GPIOs are in a power domain that 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, 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. 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_SPI0_D1 can be triggered by grounding Pin 4 on J8 MCU Header.
3.3.6.3. WKUP GPIO
Setup of WKUP GPIO is the same process of MCU GPIO. Refer to the MCU GPIO section on how to configure wakeup from WKUP GPIO.
3.3.6.4. Main I/O Daisy Chain
The system powers off the main domain when the SoC enters a low power mode. The main domain includes controllers such as Main UART, GPIO, I2C, etc. I/O daisy chaining is used in order to wakeup the SoC from peripherals that are connected to powered-off controllers. At the hardware level, all the pads in an SoC are pinmuxed to dedicated controllers like UART or GPIO.
For example, to wakeup the system from Deep Sleep via a key press on Main UART (used for Linux console logs), then simply configuring the Main UART controller as a wakeup source wouldn’t work. This is because the UART controller is powered off and wouldn’t be able to register any key press as a wakeup event. However, the UART is still connected at the “pad” level and the pads can be configured as wakeup sources by setting a specific bit in the pad register.
For detailed information and sequence please refer to I/O Power Management and Daisy Chaining section in the TRM.
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:
main_uart0 is used where a key press on the Linux console can wakeup the system.
main_gpio is used where activity on configured GPIO pin can wakeup the system.
3.3.6.4.1. Main UART
To configure UART as an I/O daisy chain wakeup, refer to the main_uart0 node in k3-am62x-sk-common.dtsi
&main_pmx0 {
main_uart0_tx_pins_default: main-uart0-tx-default-pins {
bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14/E11) UART0_TXD */
>;
};
main_uart0_rx_pins_default: main-uart0-rx-default-pins {
bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14/A13) UART0_RXD */
>;
};
main_uart0_rx_pins_wakeup: main-uart0-rx-wakeup-pins {
pinctrl-single,pins = <
AM62X_IOPAD(0x1c8, PIN_INPUT | PIN_WKUP_EN, 0) /* (D14/A13) UART0_RXD */
>;
};
};
&main_uart0 {
bootph-all;
status = "okay";
pinctrl-names = "default", "wakeup";
pinctrl-0 = <&main_uart0_tx_pins_default>, <&main_uart0_rx_pins_default>;
pinctrl-1 = <&main_uart0_tx_pins_default>, <&main_uart0_rx_pins_wakeup>;
wakeup-source = <&system_deep_sleep>,
<&system_mcu_only>,
<&system_standby>;
};
In the above code, a “wakeup” pinctrl state is defined for main_uart0. The “wakeup” pinctrl state sets the WKUP_EN flag on the desired padconfig register, which allows the pad to act as a wakeup source. During suspend, the Linux 8250_omap serial driver switches from the “default” pinctrl state to the “wakeup” pinctrl state.
This configures UART to act as a wakeup source, and a key press on same terminal should trigger a wakeup from LPM.
Any UART can be chosen according to application requirements.
3.3.6.4.2. Main GPIO
Configuring Main GPIO as an I/O daisy chain wakeup source requires a combination of gpio-keys with a chained IRQ in the pinctrl driver. Setting the 29th bit in the desired padconfig register, allows the pad to act as a wakeup source by triggering a wake IRQ in Deep Sleep states.
The reference configuration for Main GPIO wakeup can be found under gpio_key node in k3-am62x-sk-lpm-wkup-sources.dtso
gpio_key { compatible = "gpio-keys"; autorepeat; pinctrl-names = "default"; pinctrl-0 = <&main_gpio1_pins_default>; switch { label = "WKGPIO"; linux,code = <KEY_WAKEUP>; interrupts-extended = <&main_gpio1 10 IRQ_TYPE_EDGE_RISING>, <&main_pmx0 0x1a0>; interrupt-names = "irq", "wakeup"; }; };
The IRQ is chained to the pinctrl driver using the second interrupts-extended entry. The wake IRQ framework in Linux works so that the second entry gets marked as a wakeup source, and then the pinctrl driver is informed that the pad, 0x1a0 in this case, is to be configured as a wakeup pad when system enters Deep Sleep.
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@<machine>:~# 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.3.6.5. WKUP UART
The UART in WKUP domain is capable of waking up the system.
In order to use WKUP UART as a wakeup source, it needs to be configured in a generic way using the ti-sysc interconnect target module driver. The reference configuration can be found under target-module in k3-am62-wakeup.dtsi
WKUP UART is generally available on the third serial port (/dev/ttyUSB2) and by default it only shows output from DM R5.
Once the system has entered the specified low power mode as shown in the LPM section, wakeup from WKUP UART can be triggered by doing any key press on the WKUP UART terminal. No output will be visible on the WKUP UART terminal, but Linux resume messages will be printed on the MAIN UART terminal.
3.3.6.6. USB Wakeup methods
System wakeup is possible through the USB events in both Host and Device mode.
3.3.6.6.1. Host Mode Wakeup Events
The USB wakeup events in Host mode are described below:
3.3.6.6.1.1. Wakeup via a device connect event
Follow the steps described in LPM section to enter desired low power mode.
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.3.6.6.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 enter desired low power mode.
Once the system is suspended, disconnect the USB device from the board and this should wakeup the system. The device will not show up in list of USB enumerated devices. This can be verified by executing
# lsusb -t
3.3.6.6.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 enter desired low power mode.
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.3.6.6.2. Device Mode Wakeup Events
3.3.6.6.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 enter desired low power mode.
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 will 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
# lsusb -t
3.3.6.7. 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:
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] Next MCU mode is 1
[IPC RPMSG ECHO] Suspend request to MCU-only mode received
[IPC RPMSG ECHO] Press a single 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.3.6.8. CAN UART I/O Daisy Chain
It is possible to wakeup the system from CAN UART pins in all supported low power modes. This is possible once CAN UART is configured.
To set CAN UART as a wakeup source, a pinctrl state called “wakeup” needs to be added to the device tree. The “wakeup” pinctrl state will set the WKUP_EN flag on the desired padconfig register. When the WKUP_EN flag (29th bit) is set, it allows the pad to act as a wakeup source. If CAN UART has the “wakeup” pinctrl state defined, then the Linux mcan driver is able to switch to the pinctrl “wakeup” state during suspend which enables CAN UART wakeup.
The mcan_uart0 and mcan_uart1 nodes in k3-am62x-sk-lpm-io-ddr-wkup-sources.dtso can be used as a reference for enabling CAN UART wakeup.
&mcu_pmx0 {
mcu_mcan0_tx_pins_default: mcu-mcan0-tx-pins-default {
pinctrl-single,pins = <
AM62X_IOPAD(0x034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
>;
};
mcu_mcan0_rx_pins_default: mcu-mcan0-rx-pins-default {
pinctrl-single,pins = <
AM62X_IOPAD(0x038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
>;
};
mcu_mcan0_rx_pins_wakeup: mcu-mcan0-rx-pins-wakeup {
pinctrl-single,pins = <
AM62X_IOPAD(0x038, PIN_INPUT | WKUP_EN, 0) /* (B3) MCU_MCAN0_RX */
>;
};
};
&mcu_mcan0 {
pinctrl-names = "default", "wakeup";
pinctrl-0 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_default>;
pinctrl-1 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_wakeup>;
status = "okay";
};
CAN UART wakeup can be tested by using either the k3-am62x-sk-lpm-wkup-sources.dtso or k3-am62x-sk-lpm-io-ddr-wkup-sources.dtso overlays. Please refer to How to enable DT overlays for more details.
Once the system has entered any low power mode as shown in the LPM section, wakeup from MCU_GPIO0_16 or MCU_MCAN0_RX can be triggered by grounding Pin 11 or Pin 22 on J8 MCU Header, respectively.
3.3.6.9. RTC Ext Pin
This is not applicable for AM62x.
3.3.6.10. Confirming the Wakeup event type
When the SoC wakes up from any Low Power Mode, the Device Manager logs the wake reason, the pin number that triggered the wakeup, and the last low power mode entered. This wake reason and low power mode can be queried by Linux using the TISCI LPM API. The wakeup pin can be found in the datasheet by converting the pin number from hex to decimal and finding the corresponding PADCONFIG register.
This wake reason is printed as part of the Linux suspend/resume log:
[ 249.471725] CPU3 is up
[ 249.472314] ti-sci 44043000.system-controller: ti_sci: wakeup source:0x80, pin:0x72, mode:0x1
In the above example, the wakeup source of 0x80 is MAIN_IO. The 0x72 pin refers to PADCONFIG114. This means the cause of the wakeup event is UART0_RXD. The mode of 0x1 is the last low power mode entered which was MCU_ONLY.