Table of Contents
Prerequisites
- You have installed Petalinux 2018.1 (or later).
- You have created a Petalinux project using the BSP for your board.
- You were able to boot the pre-built images on your board.
- You have a stand-alone application running on the RPU that supports power management using the XilPM library. If not, see Minimal RPU Applications on how to run a minimal application on the RPU.
- The overviw of EEMI APIs described in https://www.xilinx.com/support/documentation/user_guides/ug1199-zynq-power-management.pdf
Out-of-box PM Demo
A script has been included in the pre-built PetaLinux images that demonstrate the power management features available to the Linux console. To run the demo script:
- Boot the PetaLinux pre-built image on the board.
- Log in on the Linux console, type: "hellopm"
Runtime PM
See:
https://www.kernel.org/doc/Documentation/power/runtime_pm.txtQuoting from
https://www.kernel.org/doc/html/v4.12/driver-api/pm/devices.html:- "Devices may be put into low-power states while the system is running, independently of other power management activity in principle. However, devices are not generally independent of each other (for example, a parent device cannot be suspended unless all of its child devices have been suspended)."
See documentation on the Linux drivers for any specific runtime PM handling:
Linux DriversCPU PM
CPU Hotplug
Kernel documentation:
https://www.kernel.org/doc/Documentation/power/suspend-and-cpuhotplug.txtThe required kernel configuration options are:
- Kernel Features
- [*] Support for hot-pluggable CPUs
- Power management options
- [*] Suspend to RAM and standby
The user may take one or more APU cores on-line and off-line as needed via the CPU Hotplug control interface.
For example, to take CPU3 off-line:
Code Block |
---|
|
$ echo 0 > /sys/devices/system/cpu/cpu3/online |
CPU Idle
CPU cores are powered off when they are idling.
Kernel documentation:
...
The required kernel configuration options are:
- CPU Power Management
- CPU Frequency scaling
- [*] CPU Frequency scaling
- Default CPUFreq governor
- <*> Generic DT based cpufreq driver
Read current CPU frequency (same for all cores):
Code Block |
---|
|
$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq |
Look up the available governors speeds (same for all cores):
Code Block |
---|
|
$ cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_available_governors |
Select the 'userspace' governor for CPU frequency control (same for all cores):
Code Block |
---|
|
$ echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor |
Look up the available CPU speeds (same for all cores):
Code Block |
---|
|
$ cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_available_frequencies
|
Change the CPU speed (same for all cores):
Code Block |
---|
|
$ echo <frequency> > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed |
Zynq UltraScale+ MPSoC Power Management - Linux Kernel
This page provides tips and examples of Linux kernel power management solutions for the Zynq UltraScale+ MPSoC.
System PM
Suspend
The kernel is suspended when the CPU and most of the peripherals are powered down. The system run states needed to resume from suspend is stored in the DRAM, which is put into self-refresh mode.
The required kernel configuration option settings are:
- Power management options
- [*] Suspend to RAM and standby
- [*] User space wakeup sources interface
- [*] Device power management core functionality
- Device Drivers
- SOC (System On Chip) specific Drivers
- XIlinx SoC drivers
- Zynq MPSoC SoC
- [*] Enable Xilinx Zynq MPSoC Power Management Driver
- [*] Enable Zynq MPSoC generic PM domains
- Firmware Drivers
- Zynq MPSoC Firmware Drivers
- -*- Enable Xilinx Zynq MPSoC firmware interface
Type the following command to suspend the kernel. (Note: you must enable a wake-up source first otherwise the kernel will never resume.)
Code Block |
---|
|
$ echo mem > /sys/power/state |
Wake-up Source
The kernel resumes from the suspend mode when a wake-up event occurs.
UART
To wake up the APU on UART input:
...
The debugfs interface is intended for testing and debugging the integration between the Linux kernel and the Zynq UltraScale+ MPSoC power management framework. This interface must be used with a lot of care. In fact, accessing this interface during normal PM operation will very likely cause unexpected problems. Please refer to UG1137 for the usage of PM API.
Starting with 2018.1, this interface is disabled by default. To enable this interface, change the following kernel configurations (in this order):
- Power management options
- [*] Suspend to RAM and standby
- [*] User space wakeup sources interface
- [*] Device power management core functionality
- Kernel hacking
- Compile-time checks and compiler options
- Firmware Drivers
- Zynq MPSoC Firmware Drivers
- -*- Enable Xilinx Zynq MPSoC firmware interface
- [*] Enable Xilinx Zynq MPSoC firmware debug APIs
...
Code Block |
---|
|
/sys/kernel/debug/zynqmp-firmware/pm |
Note: For 2018.1 and later releases, output of debug commands (if any) would not be printed on console in dmesg. it needs to be explicitly read by reading above "pm" debugfs file as below:
Code Block |
---|
|
cat /sys/kernel/debug/zynqmp-firmware/pm |
...
See UG1137 for the input parameters to the APIs for ZynqMP Platform. For Versal refer UG1304.
Note: For 2018.1 and later releases, API names are updated with "pm_" prefix. Get API Version
Get the API version.
Code Block |
---|
|
$ echo pm_get_api_version > (sysfs node) |
Request Suspend
Request another PU to suspend itself.
Code Block |
---|
|
$ echo pm_request_suspend <node> > (sysfs node) |
Self Suspend
Notify PMU that this PU is about to suspend itself.
Code Block |
---|
|
$ echo pm_self_suspend <node> > (sysfs node) |
Force Power Down
Force another PU to power down.
Code Block |
---|
|
$ echo pm_force_powerdown <node> > (sysfs node) |
Abort Suspend
Notify PMU that the attempt to suspend has been aborted.
Code Block |
---|
|
$ echo pm_abort_suspend > (sysfs node) |
Request Wake-up
Request another PU to wake up from suspend state.
Code Block |
---|
|
$ echo pm_request_wakeup <node> <set_address> <address> > (sysfs node) |
Set Wake-up Source
Set up a node as the wake-up source.
Code Block |
---|
|
$ echo pm_set_wakeup_source <target> <wkup_node> <enable> > (sysfs node) |
System Shutdown
Shut down the PU's own sub-system.
Code Block |
---|
|
$ echo pm_system_shutdown <action> <scope> > (sysfs node) |
Action:- 0: Shutdown
- 1: Reset
- 2: Set reset scope
Scope:
Request Node
Request to use a node.
Code Block |
---|
|
$ echo pm_request_node <node> > (sysfs node) |
Release Node
Free a node that is no longer being used.
Code Block |
---|
|
$ echo pm_release_node <node> > (sysfs node) |
Set Requirement
Set the power requirement on the node.
Code Block |
---|
|
$ echo pm_set_requirement <node> <capabilities> > (sysfs node) |
Set Max Latency
Set the maximum wake-up latency requirement for a node.
Code Block |
---|
|
$ echo pm_set_max_latency <node> <latency> > (sysfs node) |
Get Node Status
Get status information of a node. (Any PU can check the status of any node, regardless of the node assignment.)
Code Block |
---|
|
$ echo pm_get_node_status <node> > (sysfs node) |
Returns (printed to screen):
- Status: Node power status (see below.)
- Usage: The master(s) using this node (bit-map):
- Bit 0: Used by this master
- Bit 1: Used by other master(s)
- Requirement: Capabilities required (bit-map):
- Bit 0: Accessible.
- Bit 1: Retain context.
- Bit 2: Wake-up source.
Status
Node Type | 0 | 1 | 2 | 3 |
Memory | OFF | RETENTION | ON |
|
CPU PP | OFF | ON |
|
|
Processor | FORCED OFF | ACTIVE | SLEEP | SUSPENDING |
USB | NOT USED | OFF (Could be a wake-up source) | ON |
|
|
Other Nodes | OFF | ON |
|
|
Get Operating Characteristic
Get operating characteristic information of a node.
Code Block |
---|
|
$ echo pm_get_operating_characteristic <node> > (sysfs node) |
Reset Assert
To perform assert, release or pulse reset on specific reset line.
Code Block |
---|
|
$ echo pm_reset_assert <reset> <action> > (sysfs node) |
Reset Get Status
To get the status of specific reset line.
Code Block |
---|
|
$ echo pm_reset_get_status <reset> > (sysfs node) |
MMIO Read
To read a value from an address that is not directly accessible from Linux/APU.
Code Block |
---|
|
$ echo mmio_read <address> > (sysfs node) |
Address is in hex format (e.g. 0xFFFF0000). Not all addresses are accessible by all masters.
Note: MMIO read has been removed since 2018.1 release.MMIO Write
To write a value to a specific address that is not directly accessible from Linux/APU.
Code Block |
---|
|
$ echo mmio_write <mask> <address> <value> > (sysfs node) |
Mask, address and value are in hex format (e.g. 0xFFFF0000). Not all addresses are accessible by all masters.
Note: MMIO write has been removed since 2018.1 release.Get Chip ID
Get the chip ID.
Code Block |
---|
|
$ echo pm_get_chipid > (sysfs node) |
Get pin control functions
Get current selected function for given pin.
Code Block |
---|
|
$ echo pm_pinctrl_get_function <pin-number> > (sysfs node) |
Set pin control functions
Set requested function for given pin.
Code Block |
---|
|
$ echo pm_pinctrl_set_function <pin-number> <function-id> > (sysfs node) |
Get configuration parameters for the pin
Get value of requested configuration parameter for given pin.
Code Block |
---|
|
$ echo pm_pinctrl_config_param_get <pin-number> <parameter to get> > (sysfs node) |
Set configuration parameters for the pin
Set value of requested configuration parameter for given pin.
Code Block |
---|
|
$ echo pm_pinctrl_config_param_set <pin-number> <parameter to set> <param value> > (sysfs node) |
Control device and configurations
Control device and configurations and get configurations values.
Code Block |
---|
|
$ echo pm_ioctl <node id> <ioctl id> <arg1> <arg2> > (sysfs node) |
Query Data
Request data from firmware.
Code Block |
---|
|
$ echo pm_query_data <query id> <arg1> <arg2> <arg3> > (sysfs node) |
Enable Clock
Enable the clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_enable <clock id> > (sysfs node) |
Disable Clock
Disable the clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_disable <clock id> > (sysfs node) |
Get Clock State
Get the state of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_getstate <clock id> > (sysfs node)
$ cat(sysfs node) |
Set Clock Divider
Set the divider value of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_setdivider <clock id> <divider value> > (sysfs node) |
Get Clock Divider
Get the divider value of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_getdivider <clock id> > (sysfs node) |
Set Clock Rate
Set the rate of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_setrate <clock id> <clock rate> > (sysfs node) |
Note: For 2018.1 release, Set Clock Rate API is not implemented and has no effect.Get Clock Rate
Get the rate of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_getrate <clock id> > (sysfs node) |
Note: For 2018.1 release, Get Clock Rate API is not implemented and has no effect.Set Clock Parent
Set the parent of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_setparent <clock id> <parent clock id> > (sysfs node) |
Get Clock Parent
Get the parent of clock for given clock node id.
Code Block |
---|
|
$ echo pm_clock_getparent <clock id> > (sysfs node) |
CSU/PMU Register Access
Read/Write the CSU and PMU global registers.
Register Write :
Code Block |
---|
|
$ echo <address> <mask> <value> > /sys/firmware/zynqmp/config_reg |
Register Read :
Code Block |
---|
|
$ echo <address> > /sys/firmware/zynqmp/config_reg
$ cat /sys/firmware/zynqmp/config_reg |
CSU and PMU global registers are classified to two lists. White list (accessed all the time by default), Black list (accessed when a compile time flag is set)
we have a #define option (SECURE_ACCESS_VAL) that provides access to black list. To Access black list registers build the PMUFW with SECURE_ACCESS_VAL flag set.
White List Registers :
CSU Module :
PMU Global Module :
Black List Registers :
- Every other register in CSU Module, that is not covered in the above white list will be a black register.
- Every other register in PMU_GLOBAL Module, that is not covered in the above white list will be a black register.
- RSA and RSA_CORE module registers are black.