PMUFW: PM: callbacks: Added remembering and sending acknowledge for req suspend
-Added structure PmSuspendRequest for tracking suspend request related informations: which master is allowed to request whose suspend, has the request been made, etc. -Added functions in pm_master for handling requests -Added calls in pm_proc for triggering acknowledge once primary processor goes to sleep -Added sending acknowledge if target master aborts suspend -Timeouts to be implemented Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com> Acked-by: Jyotheeswar Reddy Mutthareddyvari <jyothee@xilinx.com>
This commit is contained in:
parent
416151da7e
commit
cda9f6d0a2
7 changed files with 232 additions and 7 deletions
|
@ -77,6 +77,9 @@ typedef u32 (*const PmTranHandler)(void);
|
|||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define BIT0(x) (x & 1U)
|
||||
#define TO_ACK_CB(ack, status) \
|
||||
((REQUEST_ACK_CB_STANDARD == (ack)) || \
|
||||
((REQUEST_ACK_CB_ERROR == (ack)) && (XST_SUCCESS != (status))))
|
||||
|
||||
/* All WFI bitfields in GPI2 */
|
||||
#define PMU_LOCAL_GPI2_ENABLE_ALL_PWRDN_REQ_MASK \
|
||||
|
|
|
@ -121,21 +121,48 @@ static void PmRequestSuspend(const PmMaster *const master,
|
|||
const u32 latency,
|
||||
const u32 state)
|
||||
{
|
||||
PmProc* proc = PmGetProcOfOtherMaster(master, node);
|
||||
int status;
|
||||
PmProc* proc;
|
||||
|
||||
PmDbg("(%s, %s, %d, %d)\n", PmStrNode(node), PmStrAck(ack),
|
||||
latency, state);
|
||||
|
||||
if (NULL == proc) {
|
||||
PmDbg("ERROR processor not found by node %d\n", node);
|
||||
PmProcessAckRequest(ack, master, node, XST_INVALID_PARAM, 0);
|
||||
if (REQUEST_ACK_BLOCKING == ack) {
|
||||
PmDbg("ERROR: invalid acknowledge REQUEST_ACK_BLOCKING\n");
|
||||
status = XST_INVALID_PARAM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
PmInitSuspendCb(proc->master, node, 0, 0, 0, 0);
|
||||
proc = PmGetProcOfOtherMaster(master, node);
|
||||
if (NULL == proc) {
|
||||
PmDbg("ERROR: irregular node %s\n", PmStrNode(node));
|
||||
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));
|
||||
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,
|
||||
* 3. PU does not respond to the request (timeout).
|
||||
*/
|
||||
status = PmRememberSuspendRequest(master, proc->master, ack);
|
||||
|
||||
done:
|
||||
return;
|
||||
if (XST_SUCCESS != status) {
|
||||
/* Something went wrong, acknowledge immediatelly */
|
||||
PmProcessAckRequest(ack, master, node, status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -157,5 +157,6 @@
|
|||
#define XST_PM_NO_ACCESS 2002L
|
||||
#define XST_PM_INVALID_NODE 2003L
|
||||
#define XST_PM_DOUBLE_REQ 2004L
|
||||
#define XST_PM_ABORT_SUSPEND 2005L
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "pm_sram.h"
|
||||
#include "pm_usb.h"
|
||||
#include "pm_periph.h"
|
||||
#include "pm_callbacks.h"
|
||||
#include "ipi_buffer.h"
|
||||
|
||||
/* Requirement of APU master */
|
||||
|
@ -258,6 +259,27 @@ static const PmMaster *const pmAllMasters[] = {
|
|||
&pmMasterRpu1_g,
|
||||
};
|
||||
|
||||
/*
|
||||
* Content of the array should be filled with information from PCW.
|
||||
* If a master has a priviledge to request some other master's suspend, the
|
||||
* reqMst/respMst pair has to be defined in array below. If the pair does not
|
||||
* exist, it will be considered that the requestor is not allowed to initiate
|
||||
* suspend of the target master.
|
||||
*/
|
||||
static PmSuspendRequest pmSuspRequests[] = {
|
||||
{
|
||||
.reqMst = &pmMasterApu_g,
|
||||
.respMst = &pmMasterRpu0_g,
|
||||
.flags = 0U,
|
||||
.ackReq = 0U,
|
||||
}, {
|
||||
.reqMst = &pmMasterRpu0_g,
|
||||
.respMst = &pmMasterApu_g,
|
||||
.flags = 0U,
|
||||
.ackReq = 0U,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* PmRequirementSchedule() - Schedule requirements of the master for slave.
|
||||
* Slave state will be updated according to the
|
||||
|
@ -752,6 +774,134 @@ static void PmWakeUpDisableAll(PmMaster* const master)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PmCanRequestSuspend() - Check whether master is privileged to request another
|
||||
* master to suspend
|
||||
* @reqMaster Master which requests another master to suspend
|
||||
* @respMaster Master whose suspend is requested and which is extected to
|
||||
* response to the request by initiating its own self suspend
|
||||
*
|
||||
* @return Check result
|
||||
* - True if master has privilege to request suspend
|
||||
* - False if master has no privilege
|
||||
*/
|
||||
bool PmCanRequestSuspend(const PmMaster* const reqMaster,
|
||||
const PmMaster* const respMaster)
|
||||
{
|
||||
u32 i;
|
||||
bool hasPrivilege = false;
|
||||
|
||||
for (i = 0U; i < ARRAY_SIZE(pmSuspRequests); i++) {
|
||||
if ((reqMaster == pmSuspRequests[i].reqMst) &&
|
||||
(respMaster == pmSuspRequests[i].respMst)) {
|
||||
hasPrivilege = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hasPrivilege;
|
||||
}
|
||||
|
||||
/**
|
||||
* PmIsRequestedToSuspend() - Check whether the master is requested from some
|
||||
* other master to suspend
|
||||
* @master Master to check for
|
||||
*
|
||||
* @return Check result
|
||||
* - True if master is requested to suspend
|
||||
* - False if no other master has requested this master to suspend
|
||||
*/
|
||||
bool PmIsRequestedToSuspend(const PmMaster* const master)
|
||||
{
|
||||
u32 i;
|
||||
bool requested = false;
|
||||
|
||||
for (i = 0U; i < ARRAY_SIZE(pmSuspRequests); i++) {
|
||||
if ((master == pmSuspRequests[i].respMst) &&
|
||||
(0U != (PM_REQUESTED_SUSPEND & pmSuspRequests[i].flags))) {
|
||||
requested = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return requested;
|
||||
}
|
||||
|
||||
/**
|
||||
* PmRememberSuspendRequest() - Remembers the request suspend to acknowledge
|
||||
* @reqMaster Master which requested suspend
|
||||
* @respMaster Master whose suspend is requested and which should answer
|
||||
* @ack FIXME: missing coumentation
|
||||
*
|
||||
* @return Status of the operation of remembering the requested acknowledge
|
||||
*/
|
||||
int PmRememberSuspendRequest(const PmMaster* const reqMaster,
|
||||
const PmMaster* const respMaster,
|
||||
const u32 ack)
|
||||
{
|
||||
u32 i;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Assume failure, which will be returned if reqMaster/respMaster pair
|
||||
* is not regular.
|
||||
*/
|
||||
status = XST_FAILURE;
|
||||
|
||||
for (i = 0U; i < ARRAY_SIZE(pmSuspRequests); i++) {
|
||||
if ((reqMaster == pmSuspRequests[i].reqMst) &&
|
||||
(respMaster == pmSuspRequests[i].respMst)) {
|
||||
if ((REQUEST_ACK_CB_STANDARD == ack) ||
|
||||
(REQUEST_ACK_CB_ERROR == ack)) {
|
||||
pmSuspRequests[i].ackReq = ack;
|
||||
pmSuspRequests[i].flags |= PM_REQUESTED_SUSPEND;
|
||||
status = XST_SUCCESS;
|
||||
} else {
|
||||
status = XST_PM_INTERNAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* PmMasterSuspendAck() - Acknowledge to the suspend request of another
|
||||
* master
|
||||
* @respMaster Master which is responding to the suspend request
|
||||
* @response FIXME: Missing doc
|
||||
*/
|
||||
int PmMasterSuspendAck(const PmMaster* const respMaster,
|
||||
const int response)
|
||||
{
|
||||
u32 i;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Assume to return failure, in case when there was no request to
|
||||
* suspend
|
||||
*/
|
||||
status = XST_FAILURE;
|
||||
|
||||
for (i = 0U; i < ARRAY_SIZE(pmSuspRequests); i++) {
|
||||
if ((respMaster == pmSuspRequests[i].respMst) &&
|
||||
(0U != (PM_REQUESTED_SUSPEND & pmSuspRequests[i].flags))) {
|
||||
if (TO_ACK_CB(pmSuspRequests[i].ackReq, response)) {
|
||||
PmAcknowledgeCb(pmSuspRequests[i].reqMst,
|
||||
pmSuspRequests[i].respMst->procs->node.nodeId,
|
||||
response,
|
||||
pmSuspRequests[i].respMst->procs->node.currState);
|
||||
}
|
||||
pmSuspRequests[i].flags &= ~PM_REQUESTED_SUSPEND;
|
||||
pmSuspRequests[i].ackReq = 0U;
|
||||
status = XST_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* PmMasterNotify() - Notify master channel of a state change in its primary processor
|
||||
* @master Pointer to master object which needs to be notified
|
||||
|
|
|
@ -85,6 +85,9 @@ typedef struct PmMaster PmMaster;
|
|||
#define PM_MASTER_WAKEUP_REQ_MASK 0x1U
|
||||
#define PM_MASTER_USING_SLAVE_MASK 0x2U
|
||||
|
||||
/* Suspend request related */
|
||||
#define PM_REQUESTED_SUSPEND 0x1U
|
||||
|
||||
/*********************************************************************
|
||||
* Structure definitions
|
||||
********************************************************************/
|
||||
|
@ -141,6 +144,22 @@ typedef struct PmMaster {
|
|||
const PmRequirementId reqsCnt;
|
||||
} PmMaster;
|
||||
|
||||
/**
|
||||
* PmSuspendRequest() - For tracking information about which master can/has
|
||||
* requested which master to suspend.
|
||||
* @reqMst Master which is priviledged to request suspend of respMst
|
||||
* @respMst Master which is requested to suspend and which should initiate
|
||||
* its own self suspend
|
||||
* @flags Flags storing information about the actual request
|
||||
* @ackReq Acknowledge argument provided with the request suspend call
|
||||
*/
|
||||
typedef struct {
|
||||
const PmMaster* reqMst;
|
||||
const PmMaster* respMst;
|
||||
u8 flags;
|
||||
u32 ackReq;
|
||||
} PmSuspendRequest;
|
||||
|
||||
/*********************************************************************
|
||||
* Global data declarations
|
||||
********************************************************************/
|
||||
|
@ -179,4 +198,16 @@ void PmEnableAllMasterIpis(void);
|
|||
/* Call when FPD goes down to enable GIC Proxy interrupts */
|
||||
void PmEnableProxyWake(PmMaster* const master);
|
||||
|
||||
bool PmCanRequestSuspend(const PmMaster* const reqMaster,
|
||||
const PmMaster* const respMaster);
|
||||
bool PmIsRequestedToSuspend(const PmMaster* const master);
|
||||
|
||||
int PmRememberSuspendRequest(const PmMaster* const reqMaster,
|
||||
const PmMaster* const respMaster,
|
||||
const u32 ack);
|
||||
|
||||
int PmMasterSuspendAck(const PmMaster* const respMaster,
|
||||
const int response);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -264,6 +264,14 @@ static int PmProcTrSuspendToSleep(PmProc* const proc)
|
|||
* scheduled requests for after primary processor goes to sleep.
|
||||
*/
|
||||
status = PmMasterNotify(proc->master, PM_PROC_EVENT_SLEEP);
|
||||
|
||||
if (true == PmIsRequestedToSuspend(proc->master)) {
|
||||
/*
|
||||
* Acknowledge to the requestor of the suspend that
|
||||
* suspend is completed.
|
||||
*/
|
||||
status = PmMasterSuspendAck(proc->master, status);
|
||||
}
|
||||
}
|
||||
DISABLE_WFI(proc->wfiEnableMask);
|
||||
ENABLE_WAKE(proc->wakeEnableMask);
|
||||
|
@ -367,6 +375,11 @@ int PmProcFsm(PmProc* const proc, const PmProcEvent event)
|
|||
case PM_PROC_EVENT_ABORT_SUSPEND:
|
||||
if (PM_PROC_STATE_SUSPENDING == currState) {
|
||||
status = PmProcTrSuspendToActive(proc);
|
||||
} else if (PM_PROC_STATE_ACTIVE == currState) {
|
||||
/* Processor aborting request to suspend */
|
||||
status = PmMasterSuspendAck(proc->master,
|
||||
XST_PM_ABORT_SUSPEND);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
case PM_PROC_EVENT_SLEEP:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ZYNQMP_XPFW_VERSION__H_
|
||||
#define ZYNQMP_XPFW_VERSION__H_
|
||||
#define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-31-g8df039867de7"
|
||||
#define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-32-g0e7cb08c2e45"
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue