From c064d50c141440f659640ae3f206330169ab237f Mon Sep 17 00:00:00 2001 From: Mirela Simonovic Date: Mon, 13 Jul 2015 16:30:58 -0700 Subject: [PATCH] PMUFW: PM: Added missing power up/down behavior for GpuPPs -GpuPP now has its own PmSlave derived structure and the FSM (new structure is added because there is no peripheral with exactly the same behavior - Usbs have also their own power island, but compared to them GpuPPs do not have wake-up capabilities through GIC Proxy, and GpuPPs depend on FPD while LPD is considered always-on) Signed-off-by: Mirela Simonovic Tested-by: Rohit Fule Acked-by: Jyotheeswar Reddy Mutthareddyvari --- lib/sw_apps/zynqmp_pmufw/src/pm_master.c | 4 +- lib/sw_apps/zynqmp_pmufw/src/pm_node.c | 4 +- lib/sw_apps/zynqmp_pmufw/src/pm_periph.c | 125 ++++++++++++++++---- lib/sw_apps/zynqmp_pmufw/src/pm_periph.h | 24 +++- lib/sw_apps/zynqmp_pmufw/src/pm_power.c | 4 +- lib/sw_apps/zynqmp_pmufw/src/pm_slave.c | 4 +- lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h | 2 +- 7 files changed, 132 insertions(+), 35 deletions(-) diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_master.c b/lib/sw_apps/zynqmp_pmufw/src/pm_master.c index b03a26d3..7efa39e8 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_master.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_master.c @@ -184,7 +184,7 @@ PmRequirement pmApuReq_g[PM_MASTER_APU_SLAVE_MAX] = { .nextReq = 0U, }, [PM_MASTER_APU_SLAVE_GPUPP0] = { - .slave = &pmSlaveGpuPP0_g, + .slave = &pmSlaveGpuPP0_g.slv, .requestor = &pmMasterApu_g, .info = 0U, .defaultReq = 0U, @@ -192,7 +192,7 @@ PmRequirement pmApuReq_g[PM_MASTER_APU_SLAVE_MAX] = { .nextReq = 0U, }, [PM_MASTER_APU_SLAVE_GPUPP1] = { - .slave = &pmSlaveGpuPP1_g, + .slave = &pmSlaveGpuPP1_g.slv, .requestor = &pmMasterApu_g, .info = 0U, .defaultReq = 0U, diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_node.c b/lib/sw_apps/zynqmp_pmufw/src/pm_node.c index 62e229e3..c97f4fc7 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_node.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_node.c @@ -72,8 +72,8 @@ static PmNode* const pmNodes[NODE_MAX] = { &pmSlaveDpll_g.slv.node, &pmSlaveRpll_g.slv.node, &pmSlaveIOpll_g.slv.node, - &pmSlaveGpuPP0_g.node, - &pmSlaveGpuPP1_g.node, + &pmSlaveGpuPP0_g.slv.node, + &pmSlaveGpuPP1_g.slv.node, &pmSlaveUart0_g.node, &pmSlaveUart1_g.node, &pmSlaveSpi0_g.node, diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_periph.c b/lib/sw_apps/zynqmp_pmufw/src/pm_periph.c index 036c289c..f56607a8 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_periph.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_periph.c @@ -32,6 +32,7 @@ #include "pm_common.h" #include "pm_node.h" #include "pm_master.h" +#include "xpfw_rom_interface.h" /* * Without clock/reset control, from PM perspective ttc has only one state. @@ -638,42 +639,118 @@ PmSlaveSata pmSlaveSata_g = { }, }; +/* + * States of a GPP slave (GPPs have its own power island (PI) and dependencies + * to the power parent (FPD) + */ +static const u32 PmGppStates[] = { + [PM_GPP_SLAVE_STATE_OFF] = 0U, + [PM_GPP_SLAVE_STATE_ON] = PM_CAP_ACCESS | PM_CAP_CONTEXT | PM_CAP_POWER, +}; + +/* GPP slave transitions (from which to which state slave can transits) */ +static const PmStateTran PmGppTransitions[] = { + { + .fromState = PM_GPP_SLAVE_STATE_ON, + .toState = PM_GPP_SLAVE_STATE_OFF, + }, { + .fromState = PM_GPP_SLAVE_STATE_OFF, + .toState = PM_GPP_SLAVE_STATE_ON, + }, +}; + +/** + * PmGppFsmHandler() - FSM handler of a GPP slave + * @slave Slave whose state should be changed + * @nextState State the slave should enter + * + * @return Status of performing transition action + */ +static int PmGppFsmHandler(PmSlave* const slave, const PmStateId nextState) +{ + int status = XST_PM_INTERNAL; + PmSlaveGpp* gpp = (PmSlaveGpp*)slave->node.derived; + + switch (slave->node.currState) { + case PM_GPP_SLAVE_STATE_ON: + if (PM_GPP_SLAVE_STATE_OFF == nextState) { + /* ON -> OFF*/ + status = gpp->PwrDn(); + } else { + status = XST_NO_FEATURE; + } + break; + case PM_GPP_SLAVE_STATE_OFF: + if (PM_GPP_SLAVE_STATE_ON == nextState) { + /* OFF -> ON */ + status = gpp->PwrUp(); + } else { + status = XST_NO_FEATURE; + } + break; + default: + PmDbg("ERROR: Unknown state #%d\n", slave->node.currState); + break; + } + if (XST_SUCCESS == status) { + slave->node.currState = nextState; + } + + return status; +} + +static const PmSlaveFsm slaveGPPFsm = { + .states = PmGppStates, + .statesCnt = ARRAY_SIZE(PmGppStates), + .trans = PmGppTransitions, + .transCnt = ARRAY_SIZE(PmGppTransitions), + .enterState = PmGppFsmHandler, +}; + static PmRequirement* const pmGpuPP0Reqs[] = { &pmApuReq_g[PM_MASTER_APU_SLAVE_GPUPP0], }; -PmSlave pmSlaveGpuPP0_g = { - .node = { - .derived = &pmSlaveGpuPP0_g, - .nodeId = NODE_GPU_PP_0, - .typeId = PM_TYPE_SLAVE, - .parent = &pmPowerDomainFpd_g, - .currState = PM_STD_SLAVE_STATE_ON, - .ops = NULL, +PmSlaveGpp pmSlaveGpuPP0_g = { + .slv = { + .node = { + .derived = &pmSlaveGpuPP0_g, + .nodeId = NODE_GPU_PP_0, + .typeId = PM_TYPE_SLAVE, + .parent = &pmPowerDomainFpd_g, + .currState = PM_STD_SLAVE_STATE_ON, + .ops = NULL, + }, + .reqs = pmGpuPP0Reqs, + .reqsCnt = ARRAY_SIZE(pmGpuPP0Reqs), + .wake = NULL, + .slvFsm = &slaveGPPFsm, }, - .reqs = pmGpuPP0Reqs, - .reqsCnt = ARRAY_SIZE(pmGpuPP0Reqs), - .wake = NULL, - .slvFsm = &slaveStdFsm, + .PwrDn = XpbrPwrDnPp0Handler, + .PwrUp = XpbrPwrUpPp0Handler, }; static PmRequirement* const pmGpuPP1Reqs[] = { &pmApuReq_g[PM_MASTER_APU_SLAVE_GPUPP1], }; -PmSlave pmSlaveGpuPP1_g = { - .node = { - .derived = &pmSlaveGpuPP1_g, - .nodeId = NODE_GPU_PP_1, - .typeId = PM_TYPE_SLAVE, - .parent = &pmPowerDomainFpd_g, - .currState = PM_STD_SLAVE_STATE_ON, - .ops = NULL, +PmSlaveGpp pmSlaveGpuPP1_g = { + .slv = { + .node = { + .derived = &pmSlaveGpuPP1_g, + .nodeId = NODE_GPU_PP_1, + .typeId = PM_TYPE_SLAVE, + .parent = &pmPowerDomainFpd_g, + .currState = PM_STD_SLAVE_STATE_ON, + .ops = NULL, + }, + .reqs = pmGpuPP1Reqs, + .reqsCnt = ARRAY_SIZE(pmGpuPP1Reqs), + .wake = NULL, + .slvFsm = &slaveGPPFsm, }, - .reqs = pmGpuPP1Reqs, - .reqsCnt = ARRAY_SIZE(pmGpuPP1Reqs), - .wake = NULL, - .slvFsm = &slaveStdFsm, + .PwrDn = XpbrPwrDnPp1Handler, + .PwrUp = XpbrPwrUpPp1Handler, }; static PmRequirement* const pmGdmaReqs[] = { diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_periph.h b/lib/sw_apps/zynqmp_pmufw/src/pm_periph.h index a291f0fa..5db4a7b5 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_periph.h +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_periph.h @@ -43,6 +43,14 @@ #define PM_STD_SLAVE_STATE_OFF 0U #define PM_STD_SLAVE_STATE_ON 1U +/* + * States of a slave with its own power island (PI), who has dependencies to the + * power parent (power domain) and have no wake-up capability through GIC Proxy. + * In this case, those are graphics processors + */ +#define PM_GPP_SLAVE_STATE_OFF 0U +#define PM_GPP_SLAVE_STATE_ON 1U + /* Always-on slaves, have only one state */ #define PM_AON_SLAVE_STATE 0U @@ -65,6 +73,18 @@ typedef struct PmSlaveSata { PmSlave slv; } PmSlaveSata; +/** + * PmSlaveGpp - Structure used for GPP + * @slv Base slave structure + * @PwrDn Pointer to a power down pmu-rom handler + * @PwrUp Pointer to a power up pmu-rom handler + */ +typedef struct PmSlaveGpp { + PmSlave slv; + PmTranHandler PwrDn; + PmTranHandler PwrUp; +} PmSlaveGpp; + /********************************************************************* * Global data declarations ********************************************************************/ @@ -73,8 +93,8 @@ extern PmSlaveTtc pmSlaveTtc1_g; extern PmSlaveTtc pmSlaveTtc2_g; extern PmSlaveTtc pmSlaveTtc3_g; extern PmSlaveSata pmSlaveSata_g; -extern PmSlave pmSlaveGpuPP0_g; -extern PmSlave pmSlaveGpuPP1_g; +extern PmSlaveGpp pmSlaveGpuPP0_g; +extern PmSlaveGpp pmSlaveGpuPP1_g; extern PmSlave pmSlaveUart0_g; extern PmSlave pmSlaveUart1_g; extern PmSlave pmSlaveSpi0_g; diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_power.c b/lib/sw_apps/zynqmp_pmufw/src/pm_power.c index bcf75720..b8b07507 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_power.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_power.c @@ -232,8 +232,8 @@ static PmNode* pmFpdChildren[] = { &pmSlaveApll_g.slv.node, &pmSlaveVpll_g.slv.node, &pmSlaveDpll_g.slv.node, - &pmSlaveGpuPP0_g.node, - &pmSlaveGpuPP1_g.node, + &pmSlaveGpuPP0_g.slv.node, + &pmSlaveGpuPP1_g.slv.node, &pmSlaveGdma_g.node, &pmSlaveDP_g.node, &pmSlaveAFI_g.node, diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_slave.c b/lib/sw_apps/zynqmp_pmufw/src/pm_slave.c index 1baf4e3d..dbaafe4f 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_slave.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_slave.c @@ -91,8 +91,8 @@ static PmSlave* const pmSlaves[] = { &pmSlaveDpll_g.slv, &pmSlaveRpll_g.slv, &pmSlaveIOpll_g.slv, - &pmSlaveGpuPP0_g, - &pmSlaveGpuPP1_g, + &pmSlaveGpuPP0_g.slv, + &pmSlaveGpuPP1_g.slv, &pmSlaveUart0_g, &pmSlaveUart1_g, &pmSlaveSpi0_g, diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h b/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h index 7aae8c40..605ffe44 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-50-g58d27503a2e0" + #define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-51-g520e2f4d096c" #endif