zynqmp: pm: Add support for setting suspend-to-RAM mode
Beside standard suspend-to-RAM state, Zynq MPSoC supports suspend-to-RAM state with additional power savings, called power-off suspend-to-RAM. If this mode is set, only NODE_EXTERN must be set as wake source. Standard suspend-to-RAM procedure is unchanged. This patch adds support for setting suspend mode from higher ELs and ensuring that all conditions for power-off suspend mode are set. Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> Signed-off-by: Filip Drazic <filip.drazic@aggios.com>
This commit is contained in:
parent
d744b6f56f
commit
34c571392e
|
@ -26,10 +26,15 @@
|
|||
#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1)
|
||||
#define UNDEFINED_CPUID (~0)
|
||||
|
||||
#define PM_SUSPEND_MODE_STD 0
|
||||
#define PM_SUSPEND_MODE_POWER_OFF 1
|
||||
|
||||
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
|
||||
|
||||
extern const struct pm_ipi apu_ipi;
|
||||
|
||||
static uint32_t suspend_mode = PM_SUSPEND_MODE_STD;
|
||||
|
||||
/* Order in pm_procs_all array must match cpu ids */
|
||||
static const struct pm_proc pm_procs_all[] = {
|
||||
{
|
||||
|
@ -165,6 +170,19 @@ static void pm_client_set_wakeup_sources(void)
|
|||
uint8_t pm_wakeup_nodes_set[NODE_MAX];
|
||||
uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4;
|
||||
|
||||
/* In case of power-off suspend, only NODE_EXTERN must be set */
|
||||
if (suspend_mode == PM_SUSPEND_MODE_POWER_OFF) {
|
||||
enum pm_ret_status ret;
|
||||
|
||||
ret = pm_set_wakeup_source(NODE_APU, NODE_EXTERN, 1);
|
||||
/**
|
||||
* If NODE_EXTERN could not be set as wake source, proceed with
|
||||
* standard suspend (no one will wake the system otherwise)
|
||||
*/
|
||||
if (ret == PM_RET_SUCCESS)
|
||||
return;
|
||||
}
|
||||
|
||||
zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set));
|
||||
|
||||
for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) {
|
||||
|
@ -305,3 +323,13 @@ void pm_client_wakeup(const struct pm_proc *proc)
|
|||
|
||||
bakery_lock_release(&pm_client_secure_lock);
|
||||
}
|
||||
|
||||
enum pm_ret_status pm_set_suspend_mode(uint32_t mode)
|
||||
{
|
||||
if ((mode != PM_SUSPEND_MODE_STD) &&
|
||||
(mode != PM_SUSPEND_MODE_POWER_OFF))
|
||||
return PM_RET_ERROR_ARGS;
|
||||
|
||||
suspend_mode = mode;
|
||||
return PM_RET_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ void pm_client_suspend(const struct pm_proc *proc, unsigned int state);
|
|||
void pm_client_abort_suspend(void);
|
||||
void pm_client_wakeup(const struct pm_proc *proc);
|
||||
enum pm_ret_status set_ocm_retention(void);
|
||||
enum pm_ret_status pm_set_suspend_mode(uint32_t mode);
|
||||
|
||||
/* Global variables to be set in pm_client.c */
|
||||
extern const struct pm_proc *primary_proc;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "pm_ipi.h"
|
||||
|
||||
#define PM_GET_CALLBACK_DATA 0xa01
|
||||
#define PM_SET_SUSPEND_MODE 0xa02
|
||||
#define PM_GET_TRUSTZONE_VERSION 0xa03
|
||||
|
||||
/* 0 - UP, !0 - DOWN */
|
||||
|
@ -366,6 +367,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
|||
SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
|
||||
((uint64_t)ZYNQMP_TZ_VERSION << 32));
|
||||
|
||||
case PM_SET_SUSPEND_MODE:
|
||||
ret = pm_set_suspend_mode(pm_arg[0]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
default:
|
||||
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
|
|
Loading…
Reference in New Issue