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:
Mirela Simonovic 2015-03-09 19:28:22 +01:00 committed by Nava kishore Manne
parent 416151da7e
commit cda9f6d0a2
7 changed files with 232 additions and 7 deletions

View file

@ -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 \

View file

@ -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);
}
}
/**

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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