PMUFW: PM: system_shutdown: Implemented shutdown call for shutdown argument

-Added macros in pm_defs.h for system shutdown argument 'restart'
-Exposed array of all masters needed to initiate their suspend upon
 receiving of system shutdown call
-Added checking for restart argument of system shutdown call in pm_api.c
-Implemented PmSystemShutdown for argument restart=0 (shutdown)
-Further improvement in PmSystemShutdown depend on timeout implementation

Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com>
Signed-off-by: Sören Brinkmann <soren.brinkmann@xilinx.com>
Acked-by: Jyotheeswar Reddy Mutthareddyvari <jyothee@xilinx.com>
This commit is contained in:
Mirela Simonovic 2015-03-17 12:43:12 +01:00 committed by Nava kishore Manne
parent 245017b13c
commit 4c9c9b51a9
6 changed files with 106 additions and 22 deletions

View file

@ -159,6 +159,7 @@ static PmPayloadStatus PmCheckArgument(const u8 argType,
}
break;
case ARG_ENABLE:
case ARG_RESTART:
if (arg != 1U && arg != 0U) {
status = PM_PAYLOAD_ERR_ENABLE;
}

View file

@ -110,10 +110,17 @@ done:
/**
* PmRequestSuspend() - Requested suspend by a PU for another processor
* @master PU from which the request is initiated
* @node Processor or subsystem node to be suspended
* @node PU/processor node to be suspended
* @ack Acknowledge request
* @latency Desired wakeup latency - Not supported
* @state Desired power status - Not supported
* @state Desired power state - Not supported
*
* If suspend has been successfully requested, the requested PU needs to
* initiate its own self suspend. Remember to acknowledge to the requestor
* after:
* 1. PU/processor gets powered down (after it has initiates self suspend),
* 2. PU/processor aborts suspend,
* 3. PU/processor does not respond to the request (timeout) - not supported
*/
static void PmRequestSuspend(const PmMaster *const master,
const u32 node,
@ -123,6 +130,7 @@ static void PmRequestSuspend(const PmMaster *const master,
{
int status;
PmProc* proc;
PmMaster* target = NULL;
PmDbg("(%s, %s, %d, %d)\n", PmStrNode(node), PmStrAck(ack),
latency, state);
@ -134,29 +142,43 @@ static void PmRequestSuspend(const PmMaster *const master,
}
proc = PmGetProcOfOtherMaster(master, node);
if (NULL == proc) {
PmDbg("ERROR: irregular node %s\n", PmStrNode(node));
if (NULL != proc) {
/* Node is processor, request suspend to it's master */
target = proc->master;
} else {
/* Check whether the target is placeholder in PU */
target = PmMasterGetPlaceholder(node);
}
if (NULL == target) {
PmDbg("ERROR: invalid node argument\n");
status = XST_INVALID_PARAM;
goto done;
}
if (false == PmCanRequestSuspend(master, proc->master)) {
PmDbg("ERROR: %s not allowed to request suspend of %s\n",
PmStrNode(master->procs->node.nodeId),
PmStrNode(proc->node.nodeId));
if (false == PmCanRequestSuspend(master, target)) {
PmDbg("ERROR: not allowed to request suspend of %s\n",
PmStrNode(node));
status = XST_PM_NO_ACCESS;
goto done;
}
PmInitSuspendCb(proc->master, node, SUSPEND_REASON_PU_REQ, latency,
state, MAX_LATENCY);
/*
* Suspend has been successfully requested, but the requested PU now
* needs to initiate its own self suspend. Remember to acknowledge to
* the requestor when: 1. PU gets powered down, 2. PU aborts suspend,
* Remember to acknowledge to the requestor when:
* 1. PU gets powered down, 2. PU aborts suspend,
* 3. PU does not respond to the request (timeout).
*/
status = PmRememberSuspendRequest(master, proc->master, ack);
if (REQUEST_ACK_NO != ack) {
status = PmRememberSuspendRequest(master, target, ack);
} else {
status = XST_SUCCESS;
}
if (XST_SUCCESS == status) {
/* Request is ok and saved (remembered to acknowledge) */
PmInitSuspendCb(target, node, SUSPEND_REASON_PU_REQ,
latency, state, MAX_LATENCY);
}
done:
if (XST_SUCCESS != status) {
@ -536,11 +558,27 @@ done:
/**
* PmSystemShutdown() - Request system shutdown or restart
* @master Master requesting system shutdown
* @restart Flag, 0 is for shutdown, 1 for restart
* @restart Flag, 0 is for shutdown, 1 for restart (not-supported)
*/
static void PmSystemShutdown(const PmMaster *const master, const u32 restart)
{
PmDbg("(%d) not implemented\n", restart);
u32 i;
PmDbg("(%d)\n", restart);
if (PM_SHUTDOWN == restart) {
for (i = 0U; i < ARRAY_SIZE(pmAllMasters); i++) {
/* Master requesting shutdown will suspend on its own */
if ((master != pmAllMasters[i]) &&
(PM_PROC_STATE_ACTIVE ==
pmAllMasters[i]->procs->node.currState)) {
PmInitSuspendCb(pmAllMasters[i],
pmAllMasters[i]->nid,
SUSPEND_REASON_SYS_SHUTDOWN,
MAX_LATENCY, 0, MAX_LATENCY);
}
}
}
}
/**

View file

@ -57,6 +57,10 @@
#define MAX_LATENCY (~0U)
#define MAX_QOS 100U
/* System shutdown macros */
#define PM_SHUTDOWN 0U
#define PM_RESTART 1U
/* PM API ids */
#define PM_GET_API_VERSION 1U
#define PM_SET_CONFIGURATION 2U

View file

@ -223,6 +223,7 @@ PmRequirement pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_MAX] = {
PmMaster pmMasterApu_g = {
.procs = pmApuProcs_g,
.procsCnt = PM_PROC_APU_MAX,
.nid = NODE_APU,
.ipiMask = IPI_PMU_0_IER_APU_MASK,
.pmuBuffer = IPI_BUFFER_PMU_BASE + IPI_BUFFER_TARGET_APU_OFFSET,
.buffer = IPI_BUFFER_APU_BASE + IPI_BUFFER_TARGET_PMU_OFFSET,
@ -238,6 +239,7 @@ PmMaster pmMasterApu_g = {
PmMaster pmMasterRpu0_g = {
.procs = &pmRpuProcs_g[PM_PROC_RPU_0],
.procsCnt = 1U,
.nid = NODE_RPU,
.ipiMask = IPI_PMU_0_IER_RPU_0_MASK,
.pmuBuffer = IPI_BUFFER_PMU_BASE + IPI_BUFFER_TARGET_RPU_0_OFFSET,
.buffer = IPI_BUFFER_RPU_0_BASE + IPI_BUFFER_TARGET_PMU_OFFSET,
@ -253,6 +255,7 @@ PmMaster pmMasterRpu0_g = {
PmMaster pmMasterRpu1_g = {
.procs = &pmRpuProcs_g[PM_PROC_RPU_1],
.procsCnt = 1U,
.nid = NODE_RPU_0, /* placeholder for request suspend, not used */
.ipiMask = IPI_PMU_0_IER_RPU_1_MASK,
.pmuBuffer = IPI_BUFFER_PMU_BASE + IPI_BUFFER_TARGET_RPU_1_OFFSET,
.buffer = IPI_BUFFER_RPU_1_BASE + IPI_BUFFER_TARGET_PMU_OFFSET,
@ -260,7 +263,7 @@ PmMaster pmMasterRpu1_g = {
.reqsCnt = 0U,
};
static const PmMaster *const pmAllMasters[] = {
PmMaster *const pmAllMasters[PM_MASTER_MAX] = {
&pmMasterApu_g,
&pmMasterRpu0_g,
&pmMasterRpu1_g,
@ -806,10 +809,12 @@ int PmRememberSuspendRequest(const PmMaster* const reqMaster,
int status;
/*
* Assume failure, which will be returned if reqMaster/respMaster pair
* is not regular.
* Assume that reqMaster/respMaster pair does not exist (reqMaster is
* not allowed to request suspend of respMaster). If pair
* reqMaster/respMaster is found, reqMaster is allowed to request
* suspend and status will be changed
*/
status = XST_FAILURE;
status = XST_PM_NO_ACCESS;
if (reqMaster == respMaster->pmSuspRequests.reqMst) {
if ((REQUEST_ACK_CB_STANDARD == ack) ||
@ -818,7 +823,7 @@ int PmRememberSuspendRequest(const PmMaster* const reqMaster,
respMaster->pmSuspRequests.flags |= PM_REQUESTED_SUSPEND;
status = XST_SUCCESS;
} else {
status = XST_PM_INTERNAL;
status = XST_INVALID_PARAM;
}
}
@ -899,3 +904,25 @@ int PmMasterNotify(PmMaster* const master, const PmProcEvent event)
return status;
}
/**
* PmMasterGetPlaceholder() - Check whether there is a master which holds nodeId
* @nodeId Id of the node whose placeholder should be found
*
* @return Pointer to the master if such exist, otherwise NULL
*/
PmMaster* PmMasterGetPlaceholder(const PmNodeId nodeId)
{
PmMaster* holder = NULL;
u32 i;
/* Find the master with the node placeholder */
for (i = 0U; i < ARRAY_SIZE(pmAllMasters); i++) {
if (nodeId == pmAllMasters[i]->nid) {
holder = pmAllMasters[i];
break;
}
}
return holder;
}

View file

@ -88,6 +88,9 @@ typedef struct PmMaster PmMaster;
/* Suspend request related */
#define PM_REQUESTED_SUSPEND 0x1U
/* Maximum number of masters currently supported */
#define PM_MASTER_MAX 3U
/*********************************************************************
* Structure definitions
********************************************************************/
@ -135,6 +138,13 @@ typedef struct {
* PmMaster - contains PM master related informations
* @procs Pointer to the array of processors within the master
* @procsCnt Number of processors within the master
* @nid Placeholder nodeId - used to encode request suspend for group of
* processors sharing the same communication channel. When PM
* receives this nid as request suspend argument, it initiates
* init suspend to the master. At the PU, in init_suspend_cb
* implementation, the request is mappend to actual suspend of all
* processors in the PU. In RPU case, this data could be
* initialized from PCW, based on RPU configuration.
* @ipiMask Mask dedicated to the master in IPI registers
* @pmuBuffer IPI buffer address into which PMU can write (PMU's buffer)
* @buffer IPI buffer address into which this master can write
@ -148,6 +158,7 @@ typedef struct {
typedef struct PmMaster {
PmProc* const procs;
const u8 procsCnt;
PmNodeId nid;
const u32 ipiMask;
const u32 pmuBuffer;
const u32 buffer;
@ -163,6 +174,8 @@ extern PmMaster pmMasterApu_g;
extern PmMaster pmMasterRpu0_g;
extern PmMaster pmMasterRpu1_g;
extern PmMaster *const pmAllMasters[PM_MASTER_MAX];
extern PmRequirement pmApuReq_g[PM_MASTER_APU_SLAVE_MAX];
extern PmRequirement pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_MAX];
@ -205,5 +218,6 @@ int PmRememberSuspendRequest(const PmMaster* const reqMaster,
int PmMasterSuspendAck(PmMaster* const respMaster,
const int response);
PmMaster* PmMasterGetPlaceholder(const PmNodeId nodeId);
#endif

View file

@ -1,4 +1,4 @@
#ifndef ZYNQMP_XPFW_VERSION__H_
#define ZYNQMP_XPFW_VERSION__H_
#define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-34-gd56779b12d91"
#define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-35-g982c8e2201f1"
#endif