xilinx: versal: Add support for suspend related APIs
Add support for below suspend related APIs. - self_suspend - abort_suspend - request_suspend Signed-off-by: Tejas Patel <tejas.patel@xilinx.com> Signed-off-by: Jolly Shah <jolly.shah@xilinx.com> Change-Id: If568e0cd33b64754fe66f66fc0cdd0ec62c1b32e
This commit is contained in:
parent
95794c7323
commit
fbb32695a2
|
@ -105,6 +105,8 @@
|
||||||
#define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90)
|
#define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90)
|
||||||
|
|
||||||
#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8
|
#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8
|
||||||
|
#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1
|
||||||
|
#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2
|
||||||
|
|
||||||
/* IPI registers and bitfields */
|
/* IPI registers and bitfields */
|
||||||
#define IPI0_REG_BASE 0xFF330000
|
#define IPI0_REG_BASE 0xFF330000
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <pm_common.h>
|
#include <pm_common.h>
|
||||||
#include <pm_ipi.h>
|
#include <pm_ipi.h>
|
||||||
|
#include <plat/common/platform.h>
|
||||||
#include "pm_api_sys.h"
|
#include "pm_api_sys.h"
|
||||||
#include "pm_client.h"
|
#include "pm_client.h"
|
||||||
|
|
||||||
|
@ -27,6 +28,31 @@
|
||||||
pl[0] = (uint32_t)((uint32_t)((arg0) & 0xFF) | (mid << 8)); \
|
pl[0] = (uint32_t)((uint32_t)((arg0) & 0xFF) | (mid << 8)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PM_PACK_PAYLOAD2(pl, mid, arg0, arg1) { \
|
||||||
|
pl[1] = (uint32_t)(arg1); \
|
||||||
|
PM_PACK_PAYLOAD1(pl, mid, arg0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PM_PACK_PAYLOAD3(pl, mid, arg0, arg1, arg2) { \
|
||||||
|
pl[2] = (uint32_t)(arg2); \
|
||||||
|
PM_PACK_PAYLOAD2(pl, mid, arg0, arg1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PM_PACK_PAYLOAD4(pl, mid, arg0, arg1, arg2, arg3) { \
|
||||||
|
pl[3] = (uint32_t)(arg3); \
|
||||||
|
PM_PACK_PAYLOAD3(pl, mid, arg0, arg1, arg2); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PM_PACK_PAYLOAD5(pl, mid, arg0, arg1, arg2, arg3, arg4) { \
|
||||||
|
pl[4] = (uint32_t)(arg4); \
|
||||||
|
PM_PACK_PAYLOAD4(pl, mid, arg0, arg1, arg2, arg3); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PM_PACK_PAYLOAD6(pl, mid, arg0, arg1, arg2, arg3, arg4, arg5) { \
|
||||||
|
pl[5] = (uint32_t)(arg5); \
|
||||||
|
PM_PACK_PAYLOAD5(pl, mid, arg0, arg1, arg2, arg3, arg4); \
|
||||||
|
}
|
||||||
|
|
||||||
/* PM API functions */
|
/* PM API functions */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,3 +69,92 @@ enum pm_ret_status pm_get_api_version(unsigned int *version)
|
||||||
PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_API_VERSION);
|
PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_API_VERSION);
|
||||||
return pm_ipi_send_sync(primary_proc, payload, version, 1);
|
return pm_ipi_send_sync(primary_proc, payload, version, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_self_suspend() - PM call for processor to suspend itself
|
||||||
|
* @nid Node id of the processor or subsystem
|
||||||
|
* @latency Requested maximum wakeup latency (not supported)
|
||||||
|
* @state Requested state
|
||||||
|
* @address Resume address
|
||||||
|
*
|
||||||
|
* This is a blocking call, it will return only once PMU has responded.
|
||||||
|
* On a wakeup, resume address will be automatically set by PMU.
|
||||||
|
*
|
||||||
|
* @return Returns status, either success or error+reason
|
||||||
|
*/
|
||||||
|
enum pm_ret_status pm_self_suspend(uint32_t nid,
|
||||||
|
unsigned int latency,
|
||||||
|
unsigned int state,
|
||||||
|
uintptr_t address)
|
||||||
|
{
|
||||||
|
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||||
|
unsigned int cpuid = plat_my_core_pos();
|
||||||
|
const struct pm_proc *proc = pm_get_proc(cpuid);
|
||||||
|
|
||||||
|
if (!proc) {
|
||||||
|
WARN("Failed to get proc %d\n", cpuid);
|
||||||
|
return PM_RET_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do client specific suspend operations
|
||||||
|
* (e.g. set powerdown request bit)
|
||||||
|
*/
|
||||||
|
pm_client_suspend(proc, state);
|
||||||
|
|
||||||
|
/* Send request to the PLM */
|
||||||
|
PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, PM_SELF_SUSPEND,
|
||||||
|
proc->node_id, latency, state, address,
|
||||||
|
(address >> 32));
|
||||||
|
return pm_ipi_send_sync(proc, payload, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_abort_suspend() - PM call to announce that a prior suspend request
|
||||||
|
* is to be aborted.
|
||||||
|
* @reason Reason for the abort
|
||||||
|
*
|
||||||
|
* Calling PU expects the PMU to abort the initiated suspend procedure.
|
||||||
|
* This is a non-blocking call without any acknowledge.
|
||||||
|
*
|
||||||
|
* @return Returns status, either success or error+reason
|
||||||
|
*/
|
||||||
|
enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
|
||||||
|
{
|
||||||
|
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do client specific abort suspend operations
|
||||||
|
* (e.g. enable interrupts and clear powerdown request bit)
|
||||||
|
*/
|
||||||
|
pm_client_abort_suspend();
|
||||||
|
|
||||||
|
/* Send request to the PLM */
|
||||||
|
PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_ABORT_SUSPEND, reason,
|
||||||
|
primary_proc->node_id);
|
||||||
|
return pm_ipi_send(primary_proc, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_req_suspend() - PM call to request for another PU or subsystem to
|
||||||
|
* be suspended gracefully.
|
||||||
|
* @target Node id of the targeted PU or subsystem
|
||||||
|
* @ack Flag to specify whether acknowledge is requested
|
||||||
|
* @latency Requested wakeup latency (not supported)
|
||||||
|
* @state Requested state (not supported)
|
||||||
|
*
|
||||||
|
* @return Returns status, either success or error+reason
|
||||||
|
*/
|
||||||
|
enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack,
|
||||||
|
unsigned int latency, unsigned int state)
|
||||||
|
{
|
||||||
|
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||||
|
|
||||||
|
/* Send request to the PMU */
|
||||||
|
PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_REQ_SUSPEND, target,
|
||||||
|
latency, state);
|
||||||
|
if (ack == IPI_BLOCKING)
|
||||||
|
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
|
||||||
|
else
|
||||||
|
return pm_ipi_send(primary_proc, payload);
|
||||||
|
}
|
||||||
|
|
|
@ -8,11 +8,21 @@
|
||||||
#define PM_API_SYS_H
|
#define PM_API_SYS_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "pm_defs.h"
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
* PM API function declarations
|
* PM API function declarations
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
|
|
||||||
enum pm_ret_status pm_get_api_version(unsigned int *version);
|
enum pm_ret_status pm_get_api_version(unsigned int *version);
|
||||||
|
enum pm_ret_status pm_self_suspend(uint32_t nid,
|
||||||
|
unsigned int latency,
|
||||||
|
unsigned int state,
|
||||||
|
uintptr_t address);
|
||||||
|
enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason);
|
||||||
|
enum pm_ret_status pm_req_suspend(uint32_t target,
|
||||||
|
uint8_t ack,
|
||||||
|
unsigned int latency,
|
||||||
|
unsigned int state);
|
||||||
|
|
||||||
#endif /* PM_API_SYS_H */
|
#endif /* PM_API_SYS_H */
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
#include <platform_def.h>
|
#include <platform_def.h>
|
||||||
#include <versal_def.h>
|
#include <versal_def.h>
|
||||||
#include <lib/bakery_lock.h>
|
#include <lib/bakery_lock.h>
|
||||||
|
#include <lib/mmio.h>
|
||||||
|
#include <drivers/arm/gicv3.h>
|
||||||
|
#include <plat/common/platform.h>
|
||||||
#include "pm_client.h"
|
#include "pm_client.h"
|
||||||
|
|
||||||
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
|
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
|
||||||
|
@ -28,11 +31,65 @@ static const struct pm_proc pm_procs_all[] = {
|
||||||
{
|
{
|
||||||
.node_id = XPM_DEVID_ACPU_0,
|
.node_id = XPM_DEVID_ACPU_0,
|
||||||
.ipi = &apu_ipi,
|
.ipi = &apu_ipi,
|
||||||
|
.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.node_id = XPM_DEVID_ACPU_1,
|
.node_id = XPM_DEVID_ACPU_1,
|
||||||
.ipi = &apu_ipi,
|
.ipi = &apu_ipi,
|
||||||
|
.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct pm_proc *primary_proc = &pm_procs_all[0];
|
const struct pm_proc *primary_proc = &pm_procs_all[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_client_suspend() - Client-specific suspend actions
|
||||||
|
*
|
||||||
|
* This function should contain any PU-specific actions
|
||||||
|
* required prior to sending suspend request to PMU
|
||||||
|
* Actions taken depend on the state system is suspending to.
|
||||||
|
*/
|
||||||
|
void pm_client_suspend(const struct pm_proc *proc, unsigned int state)
|
||||||
|
{
|
||||||
|
bakery_lock_get(&pm_client_secure_lock);
|
||||||
|
|
||||||
|
/* Set powerdown request */
|
||||||
|
mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
|
||||||
|
proc->pwrdn_mask);
|
||||||
|
|
||||||
|
bakery_lock_release(&pm_client_secure_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_client_abort_suspend() - Client-specific abort-suspend actions
|
||||||
|
*
|
||||||
|
* This function should contain any PU-specific actions
|
||||||
|
* required for aborting a prior suspend request
|
||||||
|
*/
|
||||||
|
void pm_client_abort_suspend(void)
|
||||||
|
{
|
||||||
|
/* Enable interrupts at processor level (for current cpu) */
|
||||||
|
gicv3_cpuif_enable(plat_my_core_pos());
|
||||||
|
|
||||||
|
bakery_lock_get(&pm_client_secure_lock);
|
||||||
|
|
||||||
|
/* Clear powerdown request */
|
||||||
|
mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
|
||||||
|
~primary_proc->pwrdn_mask);
|
||||||
|
|
||||||
|
bakery_lock_release(&pm_client_secure_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_get_proc() - returns pointer to the proc structure
|
||||||
|
* @cpuid: id of the cpu whose proc struct pointer should be returned
|
||||||
|
*
|
||||||
|
* Return: pointer to a proc structure if proc is found, otherwise NULL
|
||||||
|
*/
|
||||||
|
const struct pm_proc *pm_get_proc(unsigned int cpuid)
|
||||||
|
{
|
||||||
|
if (cpuid < ARRAY_SIZE(pm_procs_all))
|
||||||
|
return &pm_procs_all[cpuid];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
#include "pm_common.h"
|
#include "pm_common.h"
|
||||||
#include "pm_defs.h"
|
#include "pm_defs.h"
|
||||||
|
|
||||||
|
/* Functions to be implemented by each PU */
|
||||||
|
void pm_client_suspend(const struct pm_proc *proc, unsigned int state);
|
||||||
|
void pm_client_abort_suspend(void);
|
||||||
|
|
||||||
/* Global variables to be set in pm_client.c */
|
/* Global variables to be set in pm_client.c */
|
||||||
extern const struct pm_proc *primary_proc;
|
extern const struct pm_proc *primary_proc;
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,21 @@
|
||||||
|
|
||||||
/* PM API ids */
|
/* PM API ids */
|
||||||
#define PM_GET_API_VERSION 1U
|
#define PM_GET_API_VERSION 1U
|
||||||
|
#define PM_REQ_SUSPEND 6U
|
||||||
|
#define PM_SELF_SUSPEND 7U
|
||||||
|
#define PM_ABORT_SUSPEND 9U
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Enum definitions
|
* Enum definitions
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
|
enum pm_abort_reason {
|
||||||
|
ABORT_REASON_WKUP_EVENT = 100,
|
||||||
|
ABORT_REASON_PU_BUSY,
|
||||||
|
ABORT_REASON_NO_PWRDN,
|
||||||
|
ABORT_REASON_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @PM_RET_SUCCESS: success
|
* @PM_RET_SUCCESS: success
|
||||||
* @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated)
|
* @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated)
|
||||||
|
|
Loading…
Reference in New Issue