Implementing Power Management on a Processor Unit - 2020.2 English

Zynq UltraScale+ MPSoC Software Developer Guide (UG1137)

Document ID
UG1137
Release Date
2021-01-05
Version
2020.2 English

The Xilpm library provides the functions that the standalone applications executing on a processor can use to initiate the power management API calls.

See the SDK Online Help (UG782) for information on how to include the Xilpm library in a project.

Initializing the Xilpm Library

Before initiating any power management API calls, you must initialize the Xilpm library by calling XPm_InitXilpm, and passing a pointer to a properly initialized inter-processor interrupt (IPI) driver instance.

See this link to the “Interrupts” chapter of the Zynq UltraScale+ Device Technical Reference Manual (UG1085). for more information regarding IPIs.

Working with Slave Devices

The Zynq UltraScale+ MPSoC power management framework (PMF) contains functions dedicated to managing slave devices (also referred to as PM slaves), such as memories and peripherals. Processor units (PUs) use these functions to inform the power management controller about the requirements (such as capabilities and wake-up latencies) for those devices. The power management controller manages the system so that each device resides in the lowest possible power state, meeting the requirements from all eligible PUs.

Requesting and Releasing a Node

A PU uses the XPm_RequestNode API to request the access to a slave device and assert its requirements on that device. The power management controller manages the requested device's power-on and active state, provided the PU and the slave belong to the same sub-system.

After a device is no longer used, the PU typically calls the XPm_ReleaseNode function to allow the PM controller to re-evaluate the power state of that device, and potentially place it into a low-power state. It also then allows other PUs to request that device.

Changing Requirements

When a PU is using a PM slave, its requirement on the slave's capability may change. For example, an interface port may go into a low power state, or even be completely powered off, if the interface is not being used. The PU may use XPm_SetRequirement to change the capability requirement of the PM slave. Typically, the PU would not release the PM slave if it will be changing the requirement again in the future.

The following example call changes the requirement for the node argument to require wake-interrupts only:

XPm_SetRequirement(node, PM_CAP_WAKEUP, 0, REQUEST_ACK_NO);
Important: Setting requirements of a node to zero is not equivalent to releasing the PM slave. By releasing the PM slave, a PU may be allowing other PUs to use the device exclusively.

When multiple PUs share a PM slave (this applies mostly to memories), the power management controller selects a power state of the PM slave that satisfies all requirements of the requesting PUs.

The requirements on a PM slave include capability as well as latency requirements. Capability requirements may include a top capability state, some intermediate capability states, an inactive state (but with the configuration retained), and the off state. Latency requirement specifies the maximum time allowed for the PM slave to switch to the top capability state from any other state. If this time limit cannot be met, the power management controller will leave the PM slave in the top capability state regardless of other capability requirements.

Self-Suspending a CPU/PU

A PU can be a cluster of CPUs. The APU is a PU, that has four CPUs. An RPU has two CPUs, but it is considered as two PUs when running in the split mode, and one PU when it is running in the lock-step mode.

To suspend itself, a CPU must inform the power management controller about its intent by calling the XPM_SelfSuspend function. The following actions then occur:

  • After the XPm_SelfSuspend() call is processed, none of the future interrupts can prevent the CPU from entering a sleep state. To manage such behavior in the case of the APU and RPU, after the XPm_SelfSuspend() call has completed, all of the interrupts to a CPU are directed to the power management controller as GIC wake interrupts.
  • The power management controller then waits for the CPU to finalize the suspend procedure. The PU informs the power management controller that it is ready to enter a sleep state by calling XPm_SuspendFinalize.
  • The XPm_SuspendFinalize() function is architecture-dependent. It ensures that any outstanding power management API call is processed, then executes the architecture-specific suspend sequence, which also signals the suspend completion to the power management controller.
  • For Arm® processors such as the APU and RPU, the XPm_SuspendFinalize() function uses the wait for interrupt (WFI) instruction, which suspends the CPU and triggers an interrupt to the power management controller.
  • When the suspend completion is signaled to the power management controller, the power management controller places the CPU into reset, and may power down the power island of the CPU, provided that no other component within the island is currently active.
  • Interrupts enabled through the GIC interface of the CPU are redirected to the power management controller (PMC) as a GIC wake interrupt assigned to that particular CPU. Because the interrupts are redirected, the CPU can only be woken up using the power management controller.
  • Suspending a PU requires suspending all of its CPUs individually.

Resuming Execution

A CPU can be woken up either by a wake interrupt triggered by a hardware resource or by an explicit wake request using the XPM_RequestWakeup API.

The CPU starts executing from the resume address provided with the XPm_SelfSuspend call.

Setting up a Wake-up Source

The power management controller can power down the entire FPD if none of the FPD devices are in use and existing latency requirements allow this action. If the FPD is powered off and the APU is to be woken up by an interrupt triggered by a device in the LPD, the GIC Proxy must be configured to allow propagation of FPD wake events. The APU can ensure this by calling XPM_SetWakeUpSource for all devices that might need to issue wake interrupts.

Hence, prior to suspending, the APU must call XPm_SetWakeupSource(NODE_APU, node, 1) to add the required slaves as a wake-up source. The APU can then set the requirements to zero for all slaves it is using. After the APU finalizes its suspend procedure, and provided that no other PU is using any resource in the FPD, the PM controller powers off the entire FPD and configures the GIC proxy to enable propagation of the wake event of the LPD slaves.

Aborting a Suspend Procedure

If a PU decides to abort the suspend procedure after calling the XPM_SetSelfSuspend function, it must inform the power management controller about the aborted suspend by calling the XPm_AbortSuspend function.

Handling PM Slaves During the Suspend Procedure

A PU that suspends itself must inform the power management controller about its changed requirements on the peripherals and memories in use. If a PU fails inform the power management controller, all of the used devices remain powered on. Typically, for memories you must ensure that their context is preserved by using the following function:

XPm_SetRequirement(node, PM_CAP_CONTEXT, 0, REQUEST_ACK_NO);

When setting requirements for a PM slave during the suspend procedure; after calling XPM_SelfSuspend, the setting is deferred until the CPU finishes the suspend. This deference ensures that devices that are needed for completing the suspend procedure can enter a low power state after the calling CPU finishes suspend.

A common example is instruction memory, which a CPU can access until the end of a suspend. After the CPU suspends a memory, that memory can be placed into retention. All deferred requirements reverse automatically before the respective CPU is woken up.

When an entire PU suspends, the last awake CPU within the PU must manage the changes to the devices.

Example Code for Suspending an APU/RPU

There the following is an example of source code for suspending the APU or RPU:

/* Base address of vector table (reset-vector) */ extern void *_vector_table;
/* Inform PM controller that APU_0 intends to suspend */ XPm_SelfSuspend(NODE_APU_0, MAX_LATENCY, 0, (u64)&_vector_table);
/**
*	Set requirements for OCM banks to preserve their context.
*	The PM controller will defer putting OCMs into retention until the suspend is finalized
*/
XPm_SetRequirement(NODE_OCM_BANK_0, PM_CAP_CONTEXT, 0, REQUEST_ACK_NO);
XPm_SetRequirement(NODE_OCM_BANK_1, PM_CAP_CONTEXT, 0, REQUEST_ACK_NO);
XPm_SetRequirement(NODE_OCM_BANK_2, PM_CAP_CONTEXT, 0, REQUEST_ACK_NO);
XPm_SetRequirement(NODE_OCM_BANK_3, PM_CAP_CONTEXT, 0, REQUEST_ACK_NO);

/* Flush data cache */ Xil_DCacheFlush();
/* Inform PM controller that suspend procedure is completed */ XPm_SuspendFinalize();

Suspending the Entire FPD Domain

To power-down the entire full power domain, the power management controller must suspend the APU at a time when none of the FPD devices is in use. After this condition is met, the power management controller can power-down the FPD automatically. The power management controller powers down the FPD if no latency requirements constrain this action, otherwise the FPD remains powered on.

Forcefully Powering Down the FPD

There is the option to force the FPD to power-down by calling the function XPM_ForcePowerdown. This requires that the requesting PU has proper privileges configured in the power management controller. The power management controller releases all PM Slaves used by the APU automatically.

Note: This force method is typically not recommended, especially when running complex operating systems on the APU because it could result in loss of data or system corruption, due to the OS not suspending itself gracefully.
Important: Use the XPm_RequestSuspend API.