PMUFW: PM: PLL: Added PLL slaves

-Added PLL nodes (PLLs are PM slaves)
-Implemented PLL's FSM in pm_pll.h/c
-Added PmRequirement structures for APU and RPU_0, both can request
 any PLL for usage
-Implemented saving of FPD PLLs' context and powering down FPD PLLs
 before FPD gets powered down (this is PLL suspend)
-Implemented restoring of PLL states when PLL is needed for usage
 if FPD has been powered down (this is PLL resume)

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-05-31 21:13:55 -07:00 committed by Nava kishore Manne
parent 568b6a1494
commit 5ad6dc1280
11 changed files with 636 additions and 4 deletions

View file

@ -99,6 +99,16 @@ const char* PmStrNode(const u32 node)
return "NODE_TTC_0";
case NODE_SATA:
return "NODE_SATA";
case NODE_APLL:
return "NODE_APLL";
case NODE_VPLL:
return "NODE_VPLL";
case NODE_DPLL:
return "NODE_DPLL";
case NODE_RPLL:
return "NODE_RPLL";
case NODE_IOPLL:
return "NODE_IOPLL";
default:
return "ERROR_NODE";
}

View file

@ -124,9 +124,14 @@
#define NODE_USB_1 23U
#define NODE_TTC_0 24U
#define NODE_SATA 25U
#define NODE_APLL 26U
#define NODE_VPLL 27U
#define NODE_DPLL 28U
#define NODE_RPLL 29U
#define NODE_IOPLL 30U
#define NODE_MIN NODE_APU
#define NODE_MAX NODE_SATA
#define NODE_MAX NODE_IOPLL
/* Request acknowledge argument values */
#define REQUEST_ACK_NO 1U

View file

@ -40,6 +40,7 @@
#include "pm_defs.h"
#include "pm_sram.h"
#include "pm_usb.h"
#include "pm_pll.h"
#include "pm_periph.h"
#include "pm_callbacks.h"
#include "ipi_buffer.h"
@ -118,6 +119,46 @@ PmRequirement pmApuReq_g[PM_MASTER_APU_SLAVE_MAX] = {
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_APU_SLAVE_APLL] = {
.slave = &pmSlaveApll_g.slv,
.requestor = &pmMasterApu_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_APU_SLAVE_VPLL] = {
.slave = &pmSlaveVpll_g.slv,
.requestor = &pmMasterApu_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_APU_SLAVE_DPLL] = {
.slave = &pmSlaveDpll_g.slv,
.requestor = &pmMasterApu_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_APU_SLAVE_RPLL] = {
.slave = &pmSlaveRpll_g.slv,
.requestor = &pmMasterApu_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_APU_SLAVE_IOPLL] = {
.slave = &pmSlaveIOpll_g.slv,
.requestor = &pmMasterApu_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
};
/* Requirement of RPU_0 master */
@ -218,6 +259,46 @@ PmRequirement pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_MAX] = {
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_RPU_0_SLAVE_APLL] = {
.slave = &pmSlaveApll_g.slv,
.requestor = &pmMasterRpu0_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_RPU_0_SLAVE_VPLL] = {
.slave = &pmSlaveVpll_g.slv,
.requestor = &pmMasterRpu0_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_RPU_0_SLAVE_DPLL] = {
.slave = &pmSlaveDpll_g.slv,
.requestor = &pmMasterRpu0_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_RPU_0_SLAVE_RPLL] = {
.slave = &pmSlaveRpll_g.slv,
.requestor = &pmMasterRpu0_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
[PM_MASTER_RPU_0_SLAVE_IOPLL] = {
.slave = &pmSlaveIOpll_g.slv,
.requestor = &pmMasterRpu0_g,
.info = 0U,
.defaultReq = 0U,
.currReq = 0U,
.nextReq = 0U,
},
};
PmMaster pmMasterApu_g = {

View file

@ -64,7 +64,13 @@ typedef struct PmMaster PmMaster;
#define PM_MASTER_APU_SLAVE_USB1 6U
#define PM_MASTER_APU_SLAVE_TTC0 7U
#define PM_MASTER_APU_SLAVE_SATA 8U
#define PM_MASTER_APU_SLAVE_MAX 9U
#define PM_MASTER_APU_SLAVE_APLL 9U
#define PM_MASTER_APU_SLAVE_VPLL 10U
#define PM_MASTER_APU_SLAVE_DPLL 11U
#define PM_MASTER_APU_SLAVE_RPLL 12U
#define PM_MASTER_APU_SLAVE_IOPLL 13U
#define PM_MASTER_APU_SLAVE_MAX 14U
/* Rpu0 slaves */
#define PM_MASTER_RPU_0_SLAVE_TCM0A 0U
@ -79,7 +85,13 @@ typedef struct PmMaster PmMaster;
#define PM_MASTER_RPU_0_SLAVE_USB1 9U
#define PM_MASTER_RPU_0_SLAVE_TTC0 10U
#define PM_MASTER_RPU_0_SLAVE_SATA 11U
#define PM_MASTER_RPU_0_SLAVE_MAX 12U
#define PM_MASTER_RPU_0_SLAVE_APLL 12U
#define PM_MASTER_RPU_0_SLAVE_VPLL 13U
#define PM_MASTER_RPU_0_SLAVE_DPLL 14U
#define PM_MASTER_RPU_0_SLAVE_RPLL 15U
#define PM_MASTER_RPU_0_SLAVE_IOPLL 16U
#define PM_MASTER_RPU_0_SLAVE_MAX 17U
/* Pm Master request info masks */
#define PM_MASTER_WAKEUP_REQ_MASK 0x1U

View file

@ -39,6 +39,7 @@
#include "pm_sram.h"
#include "pm_usb.h"
#include "pm_periph.h"
#include "pm_pll.h"
static PmNode* const pmNodes[NODE_MAX] = {
&pmApuProcs_g[PM_PROC_APU_0].node,
@ -63,6 +64,11 @@ static PmNode* const pmNodes[NODE_MAX] = {
&pmSlaveUsb1_g.slv.node,
&pmSlaveTtc0_g.slv.node,
&pmSlaveSata_g.slv.node,
&pmSlaveApll_g.slv.node,
&pmSlaveVpll_g.slv.node,
&pmSlaveDpll_g.slv.node,
&pmSlaveRpll_g.slv.node,
&pmSlaveIOpll_g.slv.node,
};
/**

View file

@ -65,6 +65,7 @@ typedef int (*const PmNodeTranHandler)(PmNode* const nodePtr);
#define PM_TYPE_GPU_PP (PM_TYPE_SLAVE + 2U)
#define PM_TYPE_TTC (PM_TYPE_SLAVE + 3U)
#define PM_TYPE_SATA (PM_TYPE_SLAVE + 4U)
#define PM_TYPE_PLL (PM_TYPE_SLAVE + 5U)
#define IS_PROC(type) (PM_TYPE_PROC == type)

View file

@ -0,0 +1,370 @@
/*
* Copyright (C) 2014 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*/
/*********************************************************************
* Contains:
* - PLL slave implementation
* - PLL slave's FSM implementation - only tracks the PLL usage status
* (used/unused).
* - Functions for saving and restoring PLLs' context
*
* Note: PMU does not control states of PLLs. When none of FPD PLLs
* is used and FPD is going to be powered down, PMU saves context of
* PLLs in FPD and asserts their reset. After powering up FPD, PMU
* restores the state of PLL based on saved context only when PLL is
* needed for the use.
*********************************************************************/
#include "pm_pll.h"
#include "pm_master.h"
#include "pm_power.h"
#include "crf_apb.h"
#include "crl_apb.h"
#include "xpfw_util.h"
/* PLL states */
static const u32 pmPllStates[PM_PLL_STATE_MAX] = {
[PM_PLL_STATE_UNUSED] = 0U,
[PM_PLL_STATE_USED] = PM_CAP_ACCESS | PM_CAP_POWER,
};
/* PLL transition table (from which to which state PLL can transit) */
static const PmStateTran pmPllTransitions[] = {
{
.fromState = PM_PLL_STATE_USED,
.toState = PM_PLL_STATE_UNUSED,
}, {
.fromState = PM_PLL_STATE_UNUSED,
.toState = PM_PLL_STATE_USED,
},
};
/**
* PmPllBypassAndReset() - Bypass and reset/power down a PLL
* @pll Pointer to a Pll to be bypassed/reset
*/
static void PmPllBypassAndReset(PmSlavePll* const pll)
{
/* Bypass PLL before putting it into the reset */
XPfw_RMW32(pll->addr + PM_PLL_CTRL_OFFSET, PM_PLL_CTRL_BYPASS_MASK,
PM_PLL_CTRL_BYPASS_MASK);
/* Power down PLL (= reset PLL) */
XPfw_RMW32(pll->addr + PM_PLL_CTRL_OFFSET, PM_PLL_CTRL_RESET_MASK,
PM_PLL_CTRL_RESET_MASK);
}
/**
* PmPllSuspend() - Save context of PLL and power it down (reset)
* @pll Pointer to a Pll to be suspended
*/
static void PmPllSuspend(PmSlavePll* const pll)
{
u32 val;
/* Save register setting */
pll->context.ctrl = XPfw_Read32(pll->addr + PM_PLL_CTRL_OFFSET);
pll->context.cfg = XPfw_Read32(pll->addr + PM_PLL_CFG_OFFSET);
pll->context.frac = XPfw_Read32(pll->addr + PM_PLL_FRAC_OFFSET);
pll->context.toCtrl = XPfw_Read32(pll->toCtrlAddr);
pll->context.saved = true;
val = XPfw_Read32(pll->addr + PM_PLL_CTRL_OFFSET);
/* If PLL is not already in reset, bypass it and put in reset/pwrdn */
if (0U == (val & PM_PLL_CTRL_RESET_MASK)) {
PmPllBypassAndReset(pll);
}
}
/**
* PmPllResume() - Restore PLL context
* @pll Pll whose context should be restored
*
* @return Status of resume:
* - XST_SUCCESS if resumed correctly
* - XST_FAILURE if resume failed (if PLL failed to lock)
*/
static int PmPllResume(PmSlavePll* const pll)
{
int status = XST_SUCCESS;
if (true == pll->context.saved) {
/* Restore register values with reset and bypass asserted */
XPfw_Write32(pll->addr + PM_PLL_CTRL_OFFSET, pll->context.ctrl |
PM_PLL_CTRL_RESET_MASK | PM_PLL_CTRL_BYPASS_MASK);
XPfw_Write32(pll->addr + PM_PLL_CFG_OFFSET, pll->context.cfg);
XPfw_Write32(pll->addr + PM_PLL_FRAC_OFFSET, pll->context.frac);
XPfw_Write32(pll->toCtrlAddr, pll->context.toCtrl);
pll->context.saved = false;
}
if (0U != (PM_PLL_CTRL_RESET_MASK & pll->context.ctrl)) {
/* By saved/init configuration PLL is in reset, leave it as is */
goto done;
}
/* Release reset */
XPfw_RMW32(pll->addr + PM_PLL_CTRL_OFFSET, PM_PLL_CTRL_RESET_MASK,
~PM_PLL_CTRL_RESET_MASK);
/* Poll status register for the lock */
status = XPfw_UtilPollForMask(pll->statusAddr, pll->lockMask,
PM_PLL_LOCK_TIMEOUT);
if (XST_SUCCESS != status) {
/* Failed to lock PLL - assert reset and return */
XPfw_RMW32(pll->addr + PM_PLL_CTRL_OFFSET,
PM_PLL_CTRL_RESET_MASK, PM_PLL_CTRL_RESET_MASK);
goto done;
}
/* PLL is bypassed here (done by the reset) */
if (0U == (PM_PLL_CTRL_BYPASS_MASK & pll->context.ctrl)) {
/* According to saved context PLL should not be bypassed */
XPfw_RMW32(pll->addr + PM_PLL_CTRL_OFFSET,
PM_PLL_CTRL_BYPASS_MASK,
~PM_PLL_CTRL_BYPASS_MASK);
}
done:
return status;
}
/**
* PmPllFsmHandler() - PLL FSM handler
* @slave Slave whose state should be changed
* @nextState State the slave should enter
*
* @return Always XST_SUCCESS if FSM is implemented correctly
*
* Note: PLL FSM basically updates currState variable and restores PLL state
* if needed. FSM transitions cannot fail.
*/
static int PmPllFsmHandler(PmSlave* const slave, const PmStateId nextState)
{
int status;
PmSlavePll* pll = (PmSlavePll*)slave->node.derived;
switch (nextState) {
case PM_PLL_STATE_USED:
/* Resume the PLL */
status = PmPllResume(pll);
break;
case PM_PLL_STATE_UNUSED:
/* Bypassing and reseting PLL cannot fail */
PmPllBypassAndReset(pll);
status = XST_SUCCESS;
break;
default:
status = XST_PM_INTERNAL;
break;
}
if (XST_SUCCESS == status) {
slave->node.currState = nextState;
}
return status;
}
/* PLL FSM */
static const PmSlaveFsm slavePllFsm = {
.states = pmPllStates,
.statesCnt = ARRAY_SIZE(pmPllStates),
.trans = pmPllTransitions,
.transCnt = ARRAY_SIZE(pmPllTransitions),
.enterState = PmPllFsmHandler,
};
/* APLL */
static PmRequirement* const pmApllReqs[] = {
&pmApuReq_g[PM_MASTER_APU_SLAVE_APLL],
&pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_APLL],
};
PmSlavePll pmSlaveApll_g = {
.slv = {
.node = {
.derived = &pmSlaveApll_g,
.nodeId = NODE_APLL,
.typeId = PM_TYPE_PLL,
.parent = &pmPowerDomainFpd_g,
.ops = NULL,
},
.reqs = pmApllReqs,
.reqsCnt = ARRAY_SIZE(pmApllReqs),
.wake = NULL,
.slvFsm = &slavePllFsm,
},
.context = {
.saved = false,
},
.addr = CRF_APB_APLL_CTRL,
.toCtrlAddr = CRF_APB_APLL_TO_LPD_CTRL,
.statusAddr = CRF_APB_PLL_STATUS,
.lockMask = CRF_APB_PLL_STATUS_APLL_LOCK_MASK,
};
/* VPLL */
static PmRequirement* const pmVpllReqs[] = {
&pmApuReq_g[PM_MASTER_APU_SLAVE_VPLL],
&pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_VPLL],
};
PmSlavePll pmSlaveVpll_g = {
.slv = {
.node = {
.derived = &pmSlaveVpll_g,
.nodeId = NODE_VPLL,
.typeId = PM_TYPE_PLL,
.parent = &pmPowerDomainFpd_g,
.ops = NULL,
},
.reqs = pmVpllReqs,
.reqsCnt = ARRAY_SIZE(pmVpllReqs),
.wake = NULL,
.slvFsm = &slavePllFsm,
},
.context = {
.saved = false,
},
.addr = CRF_APB_VPLL_CTRL,
.toCtrlAddr = CRF_APB_VPLL_TO_LPD_CTRL,
.statusAddr = CRF_APB_PLL_STATUS,
.lockMask = CRF_APB_PLL_STATUS_VPLL_LOCK_MASK,
};
/* DPLL */
static PmRequirement* const pmDpllReqs[] = {
&pmApuReq_g[PM_MASTER_APU_SLAVE_DPLL],
&pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_DPLL],
};
PmSlavePll pmSlaveDpll_g = {
.slv = {
.node = {
.derived = &pmSlaveDpll_g,
.nodeId = NODE_DPLL,
.typeId = PM_TYPE_PLL,
.parent = &pmPowerDomainFpd_g,
.ops = NULL,
},
.reqs = pmDpllReqs,
.reqsCnt = ARRAY_SIZE(pmDpllReqs),
.wake = NULL,
.slvFsm = &slavePllFsm,
},
.context = {
.saved = false,
},
.addr = CRF_APB_DPLL_CTRL,
.toCtrlAddr = CRF_APB_DPLL_TO_LPD_CTRL,
.statusAddr = CRF_APB_PLL_STATUS,
.lockMask = CRF_APB_PLL_STATUS_DPLL_LOCK_MASK,
};
/* RPLL */
static PmRequirement* const pmRpllReqs[] = {
&pmApuReq_g[PM_MASTER_APU_SLAVE_RPLL],
&pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_RPLL],
};
PmSlavePll pmSlaveRpll_g = {
.slv = {
.node = {
.derived = &pmSlaveRpll_g,
.nodeId = NODE_RPLL,
.typeId = PM_TYPE_PLL,
.parent = NULL,
.ops = NULL,
},
.reqs = pmRpllReqs,
.reqsCnt = ARRAY_SIZE(pmRpllReqs),
.wake = NULL,
.slvFsm = &slavePllFsm,
},
.context = {
.saved = false,
},
.addr = CRL_APB_RPLL_CTRL,
.toCtrlAddr = CRL_APB_RPLL_TO_FPD_CTRL,
.statusAddr = CRL_APB_PLL_STATUS,
.lockMask = CRL_APB_PLL_STATUS_RPLL_LOCK_MASK,
};
/* IOPLL */
static PmRequirement* const pmIOpllReqs[] = {
&pmApuReq_g[PM_MASTER_APU_SLAVE_IOPLL],
&pmRpu0Req_g[PM_MASTER_RPU_0_SLAVE_IOPLL],
};
PmSlavePll pmSlaveIOpll_g = {
.slv = {
.node = {
.derived = &pmSlaveIOpll_g,
.nodeId = NODE_IOPLL,
.typeId = PM_TYPE_PLL,
.parent = NULL,
.ops = NULL,
},
.reqs = pmIOpllReqs,
.reqsCnt = ARRAY_SIZE(pmIOpllReqs),
.wake = NULL,
.slvFsm = &slavePllFsm,
},
.context = {
.saved = false,
},
.addr = CRL_APB_IOPLL_CTRL,
.toCtrlAddr = CRL_APB_IOPLL_TO_FPD_CTRL,
.statusAddr = CRL_APB_PLL_STATUS,
.lockMask = CRL_APB_PLL_STATUS_IOPLL_LOCK_MASK,
};
static PmSlavePll* const pmPlls[] = {
&pmSlaveApll_g,
&pmSlaveVpll_g,
&pmSlaveDpll_g,
&pmSlaveRpll_g,
&pmSlaveIOpll_g,
};
/**
* PmPllSuspendAll() - Suspend all PLLs whose power parent is given as argument
* @powerParent Power parent of PLLs to be suspended
*/
void PmPllSuspendAll(const PmPower* const powerParent)
{
u8 i;
for (i = 0U; i < ARRAY_SIZE(pmPlls); i++) {
if (powerParent == pmPlls[i]->slv.node.parent) {
PmPllSuspend(pmPlls[i]);
}
}
}

View file

@ -0,0 +1,136 @@
/*
* Copyright (C) 2014 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*/
/*********************************************************************
* Contains:
* - PLL slave implementation
* - Functions for saving and restoring PLLs' context
*
* Note: PMU does not control states of PLLs. When none of FPD PLLs
* is used and FPD is going to be powered down, PMU saves context of
* PLLs in FPD and asserts their reset. After powering up FPD, PMU
* restores the state of PLL based on saved context.
*********************************************************************/
#ifndef PM_PLL_H_
#define PM_PLL_H_
#include "pm_slave.h"
/*********************************************************************
* Macros
********************************************************************/
/* PLL states: */
/*
* PLL is not used by any master, so it can be powered down and it's power
* parent can be powered down as well.
*/
#define PM_PLL_STATE_UNUSED 0U
/* PLL is used by at least one master which is controlling state of PLL */
#define PM_PLL_STATE_USED 1U
#define PM_PLL_STATE_MAX 2U
/* Register offsets (in regard to PLL's base address of control registers) */
#define PM_PLL_CTRL_OFFSET 0x0U
#define PM_PLL_CFG_OFFSET 0x4U
#define PM_PLL_FRAC_OFFSET 0x8U
/* Masks of bitfields in PLL's control register */
#define PM_PLL_CTRL_RESET_MASK 0x1U
#define PM_PLL_CTRL_BYPASS_MASK 0x8U
/* Configurable: timeout period when waiting for PLL to lock */
#define PM_PLL_LOCK_TIMEOUT 0x10000U
/*********************************************************************
* Structure definitions
********************************************************************/
/**
* PmPllContext - Structure for saving context of PLL registers.
* Contains variable to store default content of:
* @ctrl Control register
* @cfg Configuration register
* @frac Fractional control register
* @toCtrl Control for a cross domain (a divisor)
* @saved Flag stating are variables of this structure containing values
* to be restored or not
*
* Note: context of the PLL is saved just before power-parent of PLL gets
* powered down (FPD for example) and then the 'saved' flag is set to true.
* In order to enter PM_PLL_STATE_USED state, PLL must have valid context,
* meaning the 'saved' flag must be false. Upon initialization (as long as
* power-parent does not get powered down), all data except 'saved' is
* invalid/not-initialized (basically 'saved' flag also states do fields of
* this structure have valid values or not).
*/
typedef struct PmPllContext {
u32 ctrl;
u32 cfg;
u32 frac;
u32 toCtrl;
bool saved;
} PmPllContext;
/**
* PmSlavePll - Structure used for Pll slave
* @slv Base slave structure
* @context Data to store context of the PLL - if after boot PLL has no
* context, it should not be initially locked by PMU, but by a
* master. To inform PMU that initially PLL has no context, this
* field should be initialized with the PM_PLL_CTRL_RESET_MASK
* set, statically or through PCW.
* @addr Base address of the PLL's control registers
* @toCtrlAddr Absolute address of cross-domain control register
* @statusAddr Address of the PLL's status register
* @lockMask Mask of the lock in status register
*/
typedef struct PmSlavePll {
PmSlave slv;
PmPllContext context;
const u32 addr;
const u32 toCtrlAddr;
const u32 statusAddr;
const u32 lockMask;
} PmSlavePll;
/*********************************************************************
* Global data declarations
********************************************************************/
extern PmSlavePll pmSlaveApll_g;
extern PmSlavePll pmSlaveDpll_g;
extern PmSlavePll pmSlaveVpll_g;
extern PmSlavePll pmSlaveRpll_g;
extern PmSlavePll pmSlaveIOpll_g;
/*********************************************************************
* Function declarations
********************************************************************/
void PmPllSuspendAll(const PmPower* const powerParent);
#endif

View file

@ -39,6 +39,7 @@
#include "pm_master.h"
#include "pm_sram.h"
#include "pm_periph.h"
#include "pm_pll.h"
#include "xpfw_rom_interface.h"
#include "crf_apb.h"
@ -105,6 +106,7 @@ static int PmPowerDownFpd(void)
int status = XpbrRstFpdHandler();
if (XST_SUCCESS == status) {
PmPllSuspendAll(&pmPowerDomainFpd_g);
PmCrfSaveContext();
status = XpbrPwrDnFpdHandler();
/*
@ -235,6 +237,9 @@ static PmNode* pmFpdChildren[] = {
&pmPowerIslandApu_g.node,
&pmSlaveL2_g.slv.node,
&pmSlaveSata_g.slv.node,
&pmSlaveApll_g.slv.node,
&pmSlaveVpll_g.slv.node,
&pmSlaveDpll_g.slv.node,
};
/* Operations for the Rpu power island */

View file

@ -40,6 +40,7 @@
#include "pm_sram.h"
#include "pm_usb.h"
#include "pm_periph.h"
#include "pm_pll.h"
#include "pm_power.h"
#include "lpd_slcr.h"
@ -82,6 +83,11 @@ static PmSlave* const pmSlaves[] = {
&pmSlaveUsb1_g.slv,
&pmSlaveTtc0_g.slv,
&pmSlaveSata_g.slv,
&pmSlaveApll_g.slv,
&pmSlaveVpll_g.slv,
&pmSlaveDpll_g.slv,
&pmSlaveRpll_g.slv,
&pmSlaveIOpll_g.slv,
};
/**

View file

@ -1,4 +1,4 @@
#ifndef ZYNQMP_XPFW_VERSION__H_
#define ZYNQMP_XPFW_VERSION__H_
#define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-40-ge46a2aec66e8"
#define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-41-g884008482155"
#endif