From 4c9c9b51a9bc15280d42a0eabde30b5df64ff5df Mon Sep 17 00:00:00 2001 From: Mirela Simonovic Date: Tue, 17 Mar 2015 12:43:12 +0100 Subject: [PATCH] PMUFW: PM: system_shutdown: Implemented shutdown call for shutdown argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -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 Signed-off-by: Sören Brinkmann Acked-by: Jyotheeswar Reddy Mutthareddyvari --- lib/sw_apps/zynqmp_pmufw/src/pm_api.c | 1 + lib/sw_apps/zynqmp_pmufw/src/pm_core.c | 70 ++++++++++++++++----- lib/sw_apps/zynqmp_pmufw/src/pm_defs.h | 4 ++ lib/sw_apps/zynqmp_pmufw/src/pm_master.c | 37 +++++++++-- lib/sw_apps/zynqmp_pmufw/src/pm_master.h | 14 +++++ lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h | 2 +- 6 files changed, 106 insertions(+), 22 deletions(-) diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_api.c b/lib/sw_apps/zynqmp_pmufw/src/pm_api.c index 044626fe..a82790aa 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_api.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_api.c @@ -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; } diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_core.c b/lib/sw_apps/zynqmp_pmufw/src/pm_core.c index 899480eb..57dc4979 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_core.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_core.c @@ -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); + } + } + } } /** diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_defs.h b/lib/sw_apps/zynqmp_pmufw/src/pm_defs.h index c3b3f3a4..2deed285 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_defs.h +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_defs.h @@ -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 diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_master.c b/lib/sw_apps/zynqmp_pmufw/src/pm_master.c index ea5d8659..d363fe5a 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_master.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_master.c @@ -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; +} diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_master.h b/lib/sw_apps/zynqmp_pmufw/src/pm_master.h index 38ba1803..2202e0a7 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_master.h +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_master.h @@ -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 diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h b/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h index 36ed2e36..2d7a133c 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h +++ b/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h @@ -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