libs:xilpm_v1_0: Adding Power Management Library for ZynqMP

swbeta2 commit 8e824dfe3b169461916c0190194a3eb5a7810b1a

xilpm provides a set of APIs which can be used by standalone applications
to call in PMUFW power management APIs via IPI. Self-suspend example is
provided to demonstrate the usage of this library.

Signed-off-by: Jyotheeswar Reddy <jyothee@xilinx.com>
This commit is contained in:
Jyotheeswar Reddy 2015-04-12 20:24:16 -07:00 committed by Nava kishore Manne
parent 91f8d3bf88
commit ef6ec50aa5
20 changed files with 7586 additions and 0 deletions

View file

@ -0,0 +1,42 @@
#/******************************************************************************
#*
#* Copyright (C) 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.
#*
#******************************************************************************/
OPTION psf_version = 2.1;
BEGIN LIBRARY xilpm
OPTION copyfiles = all;
OPTION REQUIRES_OS = (standalone);
OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxilpm,-lxil,-lgcc,-lc,--end-group";
OPTION desc = "Power Management API Library for ZynqMP";
OPTION VERSION = 1.0;
OPTION NAME = xilpm;
END LIBRARY

View file

@ -0,0 +1,105 @@
#/******************************************************************************
#*
#* Copyright (C) 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.
#*
#******************************************************************************/
proc generate {libhandle} {
# Copy over the right set of files as src based on processor type
set sw_proc_handle [hsi::get_sw_processor]
set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ]
set proctype [common::get_property IP_NAME $hw_proc_handle]
set procname [common::get_property NAME $hw_proc_handle]
set cortexa53srcdir "./src/apu"
set cortexr5srcdir "./src/rpu"
set commonsrcdir "./src/common"
foreach entry [glob -nocomplain [file join $commonsrcdir *]] {
file copy -force $entry "./src"
}
switch $proctype {
"psu_cortexa53" {
foreach entry [glob -nocomplain [file join $cortexa53srcdir *]] {
file copy -force $entry "./src/"
}
}
"psu_cortexr5" {
foreach entry [glob -nocomplain [file join $cortexr5srcdir *]] {
file copy -force $entry "./src/"
}
}
"default" {error "Error: Processor type $proctype is not supported\n"}
}
file delete -force $cortexr5srcdir
file delete -force $cortexa53srcdir
file delete -force $commonsrcdir
}
#-------
# post_generate: called after generate called on all libraries
#-------
proc post_generate {libhandle} {
xgen_opts_file $libhandle
}
#-------
# execs_generate: called after BSP's, libraries and drivers have been compiled
#-------
proc execs_generate {libhandle} {
}
proc xgen_opts_file {libhandle} {
# Copy the include files to the include directory
set srcdir src
set dstdir [file join .. .. include]
# Create dstdir if it does not exist
if { ! [file exists $dstdir] } {
file mkdir $dstdir
}
# Get list of files in the srcdir
set sources [glob -join $srcdir *.h]
# Copy each of the files in the list to dstdir
foreach source $sources {
file copy -force $source $dstdir
}
}

View file

@ -0,0 +1,128 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* Generic functions for gic initialization and interrupt enabling
*********************************************************************/
#include "gic_setup.h"
XScuGic GicInst;
/**
* GicSetupHandler() - Connect interrupt Handler to the specified interrupt number
* @IntId Interrupt id
* @PeriphInstPtr Pointer to the peripheral driver
* @Handler Interrupt Handler that for the specified peripheral
*
* @return Status of operation success (XST_* from xstatus.h)
*/
int32_t GicSetupHandler(uint32_t IntId, void *PeriphInstPtr, Xil_ExceptionHandler Handler)
{
int32_t status;
/*
* Connect a device driver Handler that will be called when an
* interrupt for the device occurs, the device driver Handler
* performs the specific interrupt processing for the device
*/
status = XScuGic_Connect(&GicInst, IntId,
Handler,
PeriphInstPtr);
return status;
}
/**
* GicEnableInterrupt() - Enable interrupt in gic
*/
void GicEnableInterrupt(uint32_t IntId)
{
XScuGic_Enable(&GicInst, IntId);
}
/**
* GicInit() - Initialize gic
*
* @return Status of operation success (XST_* from xstatus.h)
*/
int32_t GicInit()
{
int32_t Status;
XScuGic_Config *GicCfgPtr;
/* Initialize the interrupt controller driver */
GicCfgPtr = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == GicCfgPtr)
return XST_FAILURE;
Status = XScuGic_CfgInitialize(&GicInst, GicCfgPtr, GicCfgPtr->CpuBaseAddress);
if (XST_SUCCESS != Status)
return Status;
/*
* Connect the interrupt controller interrupt Handler to the
* hardware interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
&GicInst);
return XST_SUCCESS;
}
/**
* GicSetupInterruptSystem() - configure the system to receive peripheral interrupt
* @IntId interrupt id of the timer
* @PeriphInstPtr peripheral
* @Handler interrupt Handler
*
* Does everything that is needed for enabling interrupts (gic setup, Handler connecting,
* interrupt enabling on processor and gic level)
*
* @return: status of operation success (XST_* from xstatus.h)
*/
int32_t GicSetupInterruptSystem(uint32_t IntId,
void *PeriphInstPtr, Xil_ExceptionHandler Handler)
{
int32_t Status;
Status = GicInit();
if(XST_SUCCESS != Status)
return Status;
Status = GicSetupHandler(IntId, PeriphInstPtr, Handler);
if(XST_SUCCESS != Status)
return Status;
GicEnableInterrupt(IntId);
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,50 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
#ifndef _GIC_SETUP_H_
#define _GIC_SETUP_H_
#include <xscugic.h>
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
extern XScuGic GicInst;
int32_t GicSetupHandler(uint32_t IntId, void *PeriphInstPtr, Xil_ExceptionHandler Handler);
void GicEnableInterrupt(uint32_t IntId);
int32_t GicSetupInterruptSystem(uint32_t IntId,
void *PeriphInstPtr, Xil_ExceptionHandler Handler);
int32_t GicInit();
#endif

View file

@ -0,0 +1,133 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* Timer peripheral driver. Code is mostly reused from
* hello_ttc0_interrupt application.
*********************************************************************/
#include <xil_exception.h>
#include <xil_printf.h>
#include <xttcps.h>
#include "timer.h"
#include "gic_setup.h"
#include "pm_client.h"
volatile uint32_t TickCount = 0;
static XTtcPs timer0_inst;
/**
* TickHandler() - interrupt handler for timer 0
* @timer_inst: pointer to the timer instance
*/
static void TickHandler(XTtcPs *timer_inst)
{
uint32_t int_status = XTtcPs_GetInterruptStatus(timer_inst);
int_status &= XTtcPs_ReadReg(timer_inst->Config.BaseAddress, XTTCPS_IER_OFFSET);
XTtcPs_ClearInterruptStatus(timer_inst, int_status);
TickCount++;
pm_dbg("Timer0 interrupt handler, tick_count = %d\n", TickCount);
}
/**
* TimerSetIntervalMode() - This fuction sets TTC into interval mode
* @timer_inst pointer to the timer instance
* @sec interval timeout in seconds
*/
static void TimerSetIntervalMode(XTtcPs *TimerInstPtr, uint32_t PeriodInSec)
{
/* Stop the timer */
XTtcPs_Stop(TimerInstPtr);
/* Set Interval mode */
XTtcPs_SetOptions(TimerInstPtr, XTTCPS_OPTION_INTERVAL_MODE);
XTtcPs_SetInterval(TimerInstPtr, (PeriodInSec * COUNT_PER_SEC));
XTtcPs_ResetCounterValue(TimerInstPtr);
XTtcPs_SetPrescaler(TimerInstPtr, 15);
/* Enable interrupt */
XTtcPs_EnableInterrupts(TimerInstPtr, XTTCPS_IXR_INTERVAL_MASK);
}
/**
* TimerInit() - initializes timer0 device
* @timeout period for the interval timer interrupt generation
*/
int32_t TimerInit(uint32_t PeriodInSec)
{
int32_t status;
XTtcPs_Config *timer_config;
/* Look up the configuration based on the device identifier */
timer_config = XTtcPs_LookupConfig(TTC0_0_DEVICE_ID);
if (NULL == timer_config) {
return XST_FAILURE;
}
/* Initialize the device */
status = XTtcPs_CfgInitialize(&timer0_inst, timer_config, timer_config->BaseAddress);
if (XST_SUCCESS != status) {
return status;
}
/* Setup interrupts */
status = GicSetupInterruptSystem(TTC_INT_ID0,
&timer0_inst, (Xil_ExceptionHandler) TickHandler);
if (XST_SUCCESS == status) {
TimerSetIntervalMode(&timer0_inst, PeriodInSec);
XTtcPs_Start(&timer0_inst);
}
return status;
}
/**
* TimerConfigure() - configure timer to generate periodic interrupts
* timer_period Time between two timer ticks
*
* @return Status of configuration success
*/
int32_t TimerConfigure(uint32_t Period)
{
int32_t ret_status = TimerInit(Period);
switch (ret_status) {
case XST_SUCCESS:
pm_dbg("OK, configured timer\n");
break;
case XST_DEVICE_IS_STARTED:
pm_dbg("WARNING, timer is already counting\n");
break;
case XST_FAILURE:
pm_dbg("ERROR, failed to configure timer\n");
break;
default:
pm_dbg("??? unhandled status %d\n", ret_status);
break;
}
return ret_status;
}

View file

@ -0,0 +1,55 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* Timer interface, contains function to initialize timer and
* global variable tick_count which stores total number of interrupts
* generated by the timer.
*********************************************************************/
#ifndef _TIMER_H_
#define _TIMER_H_
#define TTC0_0_DEVICE_ID XPAR_XTTCPS_0_DEVICE_ID
#define COUNT_PER_SEC (XPAR_XTTCPS_0_CLOCK_HZ / 65535)
#define TTC_INT_ID0 XPAR_XTTCPS_0_INTR
#define TIMER_PERIOD 3
int32_t TimerInit(uint32_t timeout);
int32_t TimerConfigure(uint32_t timer_period);
extern volatile uint32_t TickCount;
#endif /* _TIMER_H_ */

View file

@ -0,0 +1,193 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
*
* CONTENT
* Assumptions: only PROCESSOR core is executing this code,
* other cores in PROCESSOR subsystem are already powered down.
* 1) PROCESSOR configures timer0 peripheral to generate interrupts.
* 2) PROCESSOR waits for few interrupts to be generated by the timer and
* then initiates self suspend. Before calling pm_self_suspend APU
* has saved its context (which is in this case only tick_count
* variable value) in CONTEXT memory. Suspending of the PROCESSOR is followed
* by CONTEXT retention.
* 3) Timer is still counting while PROCESSOR is suspended and the next timer
* interrupt causes CONTEXT to be woken up by PMU.
* 4) Processor resumes its execution, meaning that it restores value of
* tick_count from CONTEXT MEM and does not configure timer again because it
* is already configured. PROCESSOR enables interrupts at the processor
* level (CPSR) and handle timer interrupt that caused wake-up.
* 5) PROCESSOR waits for few more timer interrupts and repeats the suspend
* procedure.
*********************************************************************/
#include <xil_exception.h>
#include <xil_printf.h>
#include <xil_io.h>
#include <xil_cache.h>
#include <xstatus.h>
#include <sleep.h>
#include "pm_api_sys.h"
#include "timer.h"
#include "pm_client.h"
#ifdef __aarch64__
/* Use OCM for saving context */
#define CONTEXT_MEM_BASE 0xFFFC0000U
#else
/* Use TCM for saving context */
#define CONTEXT_MEM_BASE 0x20000U
#endif
/* The below sections will be saved during suspend */
extern uint8_t __data_start;
extern uint8_t __bss_start__;
extern uint8_t __data_end;
extern uint8_t __bss_end__;
/**
* SaveContext() - called to save context of bss and data sections in OCM
*/
static void SaveContext(void)
{
uint8_t *MemPtr;
uint8_t *ContextMemPtr = (uint8_t *)CONTEXT_MEM_BASE;
for (MemPtr = &__data_start; MemPtr < &__data_end; MemPtr++, ContextMemPtr++) {
*ContextMemPtr = *MemPtr;
}
for (MemPtr = &__bss_start__; MemPtr < &__bss_end__; MemPtr++, ContextMemPtr++) {
*ContextMemPtr = *MemPtr;
}
pm_dbg("Saved context (tick_count = %d)\n", TickCount);
}
/**
* RestoreContext() - called to restore context of bss and data sections from OCM
*/
static void RestoreContext(void)
{
uint8_t *MemPtr;
uint8_t *ContextMemPtr = (uint8_t *)CONTEXT_MEM_BASE;
for (MemPtr = &__data_start; MemPtr < &__data_end; MemPtr++, ContextMemPtr++) {
*MemPtr = *ContextMemPtr;
}
for (MemPtr = &__bss_start__; MemPtr < &__bss_end__; MemPtr++, ContextMemPtr++) {
*MemPtr = *ContextMemPtr;
}
pm_dbg("Restored context (tick_count = %d)\n", TickCount);
}
/**
* PrepareSuspend() - save context and request suspend
*/
static void PrepareSuspend(void)
{
SaveContext();
/* usleep is used to prevents UART prints from overlapping */
#ifdef __aarch64__
/* APU */
XPm_SelfSuspend(NODE_APU_0, MAX_LATENCY, 0);
usleep(100000);
XPm_SetRequirement(NODE_OCM_BANK_0, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
XPm_SetRequirement(NODE_OCM_BANK_1, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
XPm_SetRequirement(NODE_OCM_BANK_2, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
XPm_SetRequirement(NODE_OCM_BANK_3, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
#else
/* RPU */
XPm_SelfSuspend(NODE_RPU_0, MAX_LATENCY, 0);
usleep(100000);
XPm_SetRequirement(NODE_TCM_0_A, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
XPm_SetRequirement(NODE_TCM_0_B, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
XPm_SetRequirement(NODE_TCM_1_A, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
XPm_SetRequirement(NODE_TCM_1_B, PM_CAP_CONTEXT, 0, REQ_ACK_NO);
usleep(100000);
#endif /* __aarch64__ */
}
/**
* InitApp() - initialize interrupts and context
*/
static uint32_t InitApp(void)
{
enum XPmBootStatus status;
pm_dbg("Main\n");
/* Get boot status for APU core #0 */
status = XPm_GetBootStatus();
if (PM_INITIAL_BOOT == status) {
pm_dbg("INITIAL BOOT\n");
/* Configure timer, if configuration fails return from main */
if (XST_FAILURE == TimerConfigure(TIMER_PERIOD)) {
pm_dbg("Exiting main...\n");
return XST_FAILURE;
}
} else if (PM_RESUME == status) {
pm_dbg("RESUMED\n");
RestoreContext();
/* Timer is already counting, just enable interrupts */
Xil_ExceptionEnable();
} else {
pm_dbg("ERROR cannot identify boot reason\n");
}
return XST_SUCCESS;
}
int main(void)
{
Xil_DCacheDisable();
uint32_t Status = InitApp();
if (XST_SUCCESS != Status) {
return XST_FAILURE;
}
pm_dbg("Waiting for ticks...\n");
/* Wait for 3 timer ticks */
while ((TickCount + 1) % 4);
PrepareSuspend();
pm_dbg("Going to WFI...\n");
__asm__("wfi");
/*
* Can execute code below only if interrupt is generated between calling
* the PrepareSuspend and executing wfi. Shouldn't happen.
*/
pm_dbg("Error! WFI exit...\n");
return XST_FAILURE;
}

View file

@ -0,0 +1,614 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
#ifndef _PM_APU_H_
#define _PM_APU_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* APU Base Address
*/
#define APU_BASEADDR 0XFD5C0000
/**
* Register: APU_ERR_CTRL
*/
#define APU_ERR_CTRL ( ( APU_BASEADDR ) + 0X00000000 )
#define APU_ERR_CTRL_PSLVERR_SHIFT 0
#define APU_ERR_CTRL_PSLVERR_WIDTH 1
#define APU_ERR_CTRL_PSLVERR_MASK 0X00000001
/**
* Register: APU_ISR
*/
#define APU_ISR ( ( APU_BASEADDR ) + 0X00000010 )
#define APU_ISR_INV_APB_SHIFT 0
#define APU_ISR_INV_APB_WIDTH 1
#define APU_ISR_INV_APB_MASK 0X00000001
/**
* Register: APU_IMR
*/
#define APU_IMR ( ( APU_BASEADDR ) + 0X00000014 )
#define APU_IMR_INV_APB_SHIFT 0
#define APU_IMR_INV_APB_WIDTH 1
#define APU_IMR_INV_APB_MASK 0X00000001
/**
* Register: APU_IEN
*/
#define APU_IEN ( ( APU_BASEADDR ) + 0X00000018 )
#define APU_IEN_INV_APB_SHIFT 0
#define APU_IEN_INV_APB_WIDTH 1
#define APU_IEN_INV_APB_MASK 0X00000001
/**
* Register: APU_IDS
*/
#define APU_IDS ( ( APU_BASEADDR ) + 0X0000001C )
#define APU_IDS_INV_APB_SHIFT 0
#define APU_IDS_INV_APB_WIDTH 1
#define APU_IDS_INV_APB_MASK 0X00000001
/**
* Register: APU_CONFIG_0
*/
#define APU_CONFIG_0 ( ( APU_BASEADDR ) + 0X00000020 )
#define APU_CONFIG_0_CFGTE_SHIFT 24
#define APU_CONFIG_0_CFGTE_WIDTH 4
#define APU_CONFIG_0_CFGTE_MASK 0X0F000000
#define APU_CONFIG_0_CFGEND_SHIFT 16
#define APU_CONFIG_0_CFGEND_WIDTH 4
#define APU_CONFIG_0_CFGEND_MASK 0X000F0000
#define APU_CONFIG_0_VINITHI_SHIFT 8
#define APU_CONFIG_0_VINITHI_WIDTH 4
#define APU_CONFIG_0_VINITHI_MASK 0X00000F00
#define APU_CONFIG_0_AA64NAA32_SHIFT 0
#define APU_CONFIG_0_AA64NAA32_WIDTH 4
#define APU_CONFIG_0_AA64NAA32_MASK 0X0000000F
/**
* Register: APU_CONFIG_1
*/
#define APU_CONFIG_1 ( ( APU_BASEADDR ) + 0X00000024 )
#define APU_CONFIG_1_L2RSTDISABLE_SHIFT 29
#define APU_CONFIG_1_L2RSTDISABLE_WIDTH 1
#define APU_CONFIG_1_L2RSTDISABLE_MASK 0X20000000
#define APU_CONFIG_1_L1RSTDISABLE_SHIFT 28
#define APU_CONFIG_1_L1RSTDISABLE_WIDTH 1
#define APU_CONFIG_1_L1RSTDISABLE_MASK 0X10000000
#define APU_CONFIG_1_CP15DISABLE_SHIFT 0
#define APU_CONFIG_1_CP15DISABLE_WIDTH 4
#define APU_CONFIG_1_CP15DISABLE_MASK 0X0000000F
/**
* Register: APU_RVBARADDR0L
*/
#define APU_RVBARADDR0L ( ( APU_BASEADDR ) + 0X00000040 )
#define APU_RVBARADDR0L_ADDR_SHIFT 2
#define APU_RVBARADDR0L_ADDR_WIDTH 30
#define APU_RVBARADDR0L_ADDR_MASK 0XFFFFFFFC
/**
* Register: APU_RVBARADDR0H
*/
#define APU_RVBARADDR0H ( ( APU_BASEADDR ) + 0X00000044 )
#define APU_RVBARADDR0H_ADDR_SHIFT 0
#define APU_RVBARADDR0H_ADDR_WIDTH 8
#define APU_RVBARADDR0H_ADDR_MASK 0X000000FF
/**
* Register: APU_RVBARADDR1L
*/
#define APU_RVBARADDR1L ( ( APU_BASEADDR ) + 0X00000048 )
#define APU_RVBARADDR1L_ADDR_SHIFT 2
#define APU_RVBARADDR1L_ADDR_WIDTH 30
#define APU_RVBARADDR1L_ADDR_MASK 0XFFFFFFFC
/**
* Register: APU_RVBARADDR1H
*/
#define APU_RVBARADDR1H ( ( APU_BASEADDR ) + 0X0000004C )
#define APU_RVBARADDR1H_ADDR_SHIFT 0
#define APU_RVBARADDR1H_ADDR_WIDTH 8
#define APU_RVBARADDR1H_ADDR_MASK 0X000000FF
/**
* Register: APU_RVBARADDR2L
*/
#define APU_RVBARADDR2L ( ( APU_BASEADDR ) + 0X00000050 )
#define APU_RVBARADDR2L_ADDR_SHIFT 2
#define APU_RVBARADDR2L_ADDR_WIDTH 30
#define APU_RVBARADDR2L_ADDR_MASK 0XFFFFFFFC
/**
* Register: APU_RVBARADDR2H
*/
#define APU_RVBARADDR2H ( ( APU_BASEADDR ) + 0X00000054 )
#define APU_RVBARADDR2H_ADDR_SHIFT 0
#define APU_RVBARADDR2H_ADDR_WIDTH 8
#define APU_RVBARADDR2H_ADDR_MASK 0X000000FF
/**
* Register: APU_RVBARADDR3L
*/
#define APU_RVBARADDR3L ( ( APU_BASEADDR ) + 0X00000058 )
#define APU_RVBARADDR3L_ADDR_SHIFT 2
#define APU_RVBARADDR3L_ADDR_WIDTH 30
#define APU_RVBARADDR3L_ADDR_MASK 0XFFFFFFFC
/**
* Register: APU_RVBARADDR3H
*/
#define APU_RVBARADDR3H ( ( APU_BASEADDR ) + 0X0000005C )
#define APU_RVBARADDR3H_ADDR_SHIFT 0
#define APU_RVBARADDR3H_ADDR_WIDTH 8
#define APU_RVBARADDR3H_ADDR_MASK 0X000000FF
/**
* Register: APU_ACE_CTRL
*/
#define APU_ACE_CTRL ( ( APU_BASEADDR ) + 0X00000060 )
#define APU_ACE_CTRL_AWQOS_SHIFT 16
#define APU_ACE_CTRL_AWQOS_WIDTH 4
#define APU_ACE_CTRL_AWQOS_MASK 0X000F0000
#define APU_ACE_CTRL_ARQOS_SHIFT 0
#define APU_ACE_CTRL_ARQOS_WIDTH 4
#define APU_ACE_CTRL_ARQOS_MASK 0X0000000F
/**
* Register: APU_SNOOP_CTRL
*/
#define APU_SNOOP_CTRL ( ( APU_BASEADDR ) + 0X00000080 )
#define APU_SNOOP_CTRL_ACE_INACT_SHIFT 4
#define APU_SNOOP_CTRL_ACE_INACT_WIDTH 1
#define APU_SNOOP_CTRL_ACE_INACT_MASK 0X00000010
#define APU_SNOOP_CTRL_ACP_INACT_SHIFT 0
#define APU_SNOOP_CTRL_ACP_INACT_WIDTH 1
#define APU_SNOOP_CTRL_ACP_INACT_MASK 0X00000001
/**
* Register: APU_PWRCTL
*/
#define APU_PWRCTL ( ( APU_BASEADDR ) + 0X00000090 )
#define APU_PWRCTL_CLREXMONREQ_SHIFT 17
#define APU_PWRCTL_CLREXMONREQ_WIDTH 1
#define APU_PWRCTL_CLREXMONREQ_MASK 0X00020000
#define APU_PWRCTL_L2FLUSHREQ_SHIFT 16
#define APU_PWRCTL_L2FLUSHREQ_WIDTH 1
#define APU_PWRCTL_L2FLUSHREQ_MASK 0X00010000
#define APU_PWRCTL_CPUPWRDWNREQ_SHIFT 0
#define APU_PWRCTL_CPUPWRDWNREQ_WIDTH 4
#define APU_PWRCTL_CPUPWRDWNREQ_MASK 0X0000000F
/**
* Register: APU_PWRSTAT
*/
#define APU_PWRSTAT ( ( APU_BASEADDR ) + 0X00000094 )
#define APU_PWRSTAT_CLREXMONACK_SHIFT 17
#define APU_PWRSTAT_CLREXMONACK_WIDTH 1
#define APU_PWRSTAT_CLREXMONACK_MASK 0X00020000
#define APU_PWRSTAT_L2FLUSHDONE_SHIFT 16
#define APU_PWRSTAT_L2FLUSHDONE_WIDTH 1
#define APU_PWRSTAT_L2FLUSHDONE_MASK 0X00010000
#define APU_PWRSTAT_DBGNOPWRDWN_SHIFT 0
#define APU_PWRSTAT_DBGNOPWRDWN_WIDTH 4
#define APU_PWRSTAT_DBGNOPWRDWN_MASK 0X0000000F
/**
* Register: APU_ECO
*/
#define APU_ECO ( ( APU_BASEADDR ) + 0X000000EC )
#define APU_ECO_SPARE_SHIFT 0
#define APU_ECO_SPARE_WIDTH 32
#define APU_ECO_SPARE_MASK 0XFFFFFFFF
/**
* Register: APU_RAM_ADJ_0
*/
#define APU_RAM_ADJ_0 ( ( APU_BASEADDR ) + 0X000000F0 )
#define APU_RAM_ADJ_0_L1_ITAG_EMAS_SHIFT 29
#define APU_RAM_ADJ_0_L1_ITAG_EMAS_WIDTH 1
#define APU_RAM_ADJ_0_L1_ITAG_EMAS_MASK 0X20000000
#define APU_RAM_ADJ_0_L1_ITAG_EMAW_SHIFT 27
#define APU_RAM_ADJ_0_L1_ITAG_EMAW_WIDTH 2
#define APU_RAM_ADJ_0_L1_ITAG_EMAW_MASK 0X18000000
#define APU_RAM_ADJ_0_L1_ITAG_EMA_SHIFT 24
#define APU_RAM_ADJ_0_L1_ITAG_EMA_WIDTH 3
#define APU_RAM_ADJ_0_L1_ITAG_EMA_MASK 0X07000000
#define APU_RAM_ADJ_0_L1_IDATA_EMAS_SHIFT 21
#define APU_RAM_ADJ_0_L1_IDATA_EMAS_WIDTH 1
#define APU_RAM_ADJ_0_L1_IDATA_EMAS_MASK 0X00200000
#define APU_RAM_ADJ_0_L1_IDATA_EMAW_SHIFT 19
#define APU_RAM_ADJ_0_L1_IDATA_EMAW_WIDTH 2
#define APU_RAM_ADJ_0_L1_IDATA_EMAW_MASK 0X00180000
#define APU_RAM_ADJ_0_L1_IDATA_EMA_SHIFT 16
#define APU_RAM_ADJ_0_L1_IDATA_EMA_WIDTH 3
#define APU_RAM_ADJ_0_L1_IDATA_EMA_MASK 0X00070000
#define APU_RAM_ADJ_0_L1_DTAG_EMAS_SHIFT 13
#define APU_RAM_ADJ_0_L1_DTAG_EMAS_WIDTH 1
#define APU_RAM_ADJ_0_L1_DTAG_EMAS_MASK 0X00002000
#define APU_RAM_ADJ_0_L1_DTAG_EMAW_SHIFT 11
#define APU_RAM_ADJ_0_L1_DTAG_EMAW_WIDTH 2
#define APU_RAM_ADJ_0_L1_DTAG_EMAW_MASK 0X00001800
#define APU_RAM_ADJ_0_L1_DTAG_EMA_SHIFT 8
#define APU_RAM_ADJ_0_L1_DTAG_EMA_WIDTH 3
#define APU_RAM_ADJ_0_L1_DTAG_EMA_MASK 0X00000700
#define APU_RAM_ADJ_0_L1_DDATA_EMAS_SHIFT 5
#define APU_RAM_ADJ_0_L1_DDATA_EMAS_WIDTH 1
#define APU_RAM_ADJ_0_L1_DDATA_EMAS_MASK 0X00000020
#define APU_RAM_ADJ_0_L1_DDATA_EMAW_SHIFT 3
#define APU_RAM_ADJ_0_L1_DDATA_EMAW_WIDTH 2
#define APU_RAM_ADJ_0_L1_DDATA_EMAW_MASK 0X00000018
#define APU_RAM_ADJ_0_L1_DDATA_EMA_SHIFT 0
#define APU_RAM_ADJ_0_L1_DDATA_EMA_WIDTH 3
#define APU_RAM_ADJ_0_L1_DDATA_EMA_MASK 0X00000007
/**
* Register: APU_RAM_ADJ_1
*/
#define APU_RAM_ADJ_1 ( ( APU_BASEADDR ) + 0X000000F4 )
#define APU_RAM_ADJ_1_TLB_EMAS_SHIFT 29
#define APU_RAM_ADJ_1_TLB_EMAS_WIDTH 1
#define APU_RAM_ADJ_1_TLB_EMAS_MASK 0X20000000
#define APU_RAM_ADJ_1_TLB_EMAW_SHIFT 27
#define APU_RAM_ADJ_1_TLB_EMAW_WIDTH 2
#define APU_RAM_ADJ_1_TLB_EMAW_MASK 0X18000000
#define APU_RAM_ADJ_1_TLB_EMA_SHIFT 24
#define APU_RAM_ADJ_1_TLB_EMA_WIDTH 3
#define APU_RAM_ADJ_1_TLB_EMA_MASK 0X07000000
#define APU_RAM_ADJ_1_DIRTY_EMAS_SHIFT 21
#define APU_RAM_ADJ_1_DIRTY_EMAS_WIDTH 1
#define APU_RAM_ADJ_1_DIRTY_EMAS_MASK 0X00200000
#define APU_RAM_ADJ_1_DIRTY_EMAW_SHIFT 19
#define APU_RAM_ADJ_1_DIRTY_EMAW_WIDTH 2
#define APU_RAM_ADJ_1_DIRTY_EMAW_MASK 0X00180000
#define APU_RAM_ADJ_1_DIRTY_EMA_SHIFT 16
#define APU_RAM_ADJ_1_DIRTY_EMA_WIDTH 3
#define APU_RAM_ADJ_1_DIRTY_EMA_MASK 0X00070000
#define APU_RAM_ADJ_1_BTAC1_EMAS_SHIFT 13
#define APU_RAM_ADJ_1_BTAC1_EMAS_WIDTH 1
#define APU_RAM_ADJ_1_BTAC1_EMAS_MASK 0X00002000
#define APU_RAM_ADJ_1_BTAC1_EMAW_SHIFT 11
#define APU_RAM_ADJ_1_BTAC1_EMAW_WIDTH 2
#define APU_RAM_ADJ_1_BTAC1_EMAW_MASK 0X00001800
#define APU_RAM_ADJ_1_BTAC1_EMA_SHIFT 8
#define APU_RAM_ADJ_1_BTAC1_EMA_WIDTH 3
#define APU_RAM_ADJ_1_BTAC1_EMA_MASK 0X00000700
#define APU_RAM_ADJ_1_BTAC0_EMAS_SHIFT 5
#define APU_RAM_ADJ_1_BTAC0_EMAS_WIDTH 1
#define APU_RAM_ADJ_1_BTAC0_EMAS_MASK 0X00000020
#define APU_RAM_ADJ_1_BTAC0_EMAW_SHIFT 3
#define APU_RAM_ADJ_1_BTAC0_EMAW_WIDTH 2
#define APU_RAM_ADJ_1_BTAC0_EMAW_MASK 0X00000018
#define APU_RAM_ADJ_1_BTAC0_EMA_SHIFT 0
#define APU_RAM_ADJ_1_BTAC0_EMA_WIDTH 3
#define APU_RAM_ADJ_1_BTAC0_EMA_MASK 0X00000007
/**
* Register: APU_RAM_ADJ_2
*/
#define APU_RAM_ADJ_2 ( ( APU_BASEADDR ) + 0X000000F8 )
#define APU_RAM_ADJ_2_ETF_EMAS_SHIFT 29
#define APU_RAM_ADJ_2_ETF_EMAS_WIDTH 1
#define APU_RAM_ADJ_2_ETF_EMAS_MASK 0X20000000
#define APU_RAM_ADJ_2_ETF_EMAW_SHIFT 27
#define APU_RAM_ADJ_2_ETF_EMAW_WIDTH 2
#define APU_RAM_ADJ_2_ETF_EMAW_MASK 0X18000000
#define APU_RAM_ADJ_2_ETF_EMA_SHIFT 24
#define APU_RAM_ADJ_2_ETF_EMA_WIDTH 3
#define APU_RAM_ADJ_2_ETF_EMA_MASK 0X07000000
#define APU_RAM_ADJ_2_SCU_TAG_EMAS_SHIFT 13
#define APU_RAM_ADJ_2_SCU_TAG_EMAS_WIDTH 1
#define APU_RAM_ADJ_2_SCU_TAG_EMAS_MASK 0X00002000
#define APU_RAM_ADJ_2_SCU_TAG_EMAW_SHIFT 11
#define APU_RAM_ADJ_2_SCU_TAG_EMAW_WIDTH 2
#define APU_RAM_ADJ_2_SCU_TAG_EMAW_MASK 0X00001800
#define APU_RAM_ADJ_2_SCU_TAG_EMA_SHIFT 8
#define APU_RAM_ADJ_2_SCU_TAG_EMA_WIDTH 3
#define APU_RAM_ADJ_2_SCU_TAG_EMA_MASK 0X00000700
#define APU_RAM_ADJ_2_L2_VICTIM_EMAS_SHIFT 5
#define APU_RAM_ADJ_2_L2_VICTIM_EMAS_WIDTH 1
#define APU_RAM_ADJ_2_L2_VICTIM_EMAS_MASK 0X00000020
#define APU_RAM_ADJ_2_L2_VICTIM_EMAW_SHIFT 3
#define APU_RAM_ADJ_2_L2_VICTIM_EMAW_WIDTH 2
#define APU_RAM_ADJ_2_L2_VICTIM_EMAW_MASK 0X00000018
#define APU_RAM_ADJ_2_L2_VICTIM_EMA_SHIFT 0
#define APU_RAM_ADJ_2_L2_VICTIM_EMA_WIDTH 3
#define APU_RAM_ADJ_2_L2_VICTIM_EMA_MASK 0X00000007
/**
* Register: APU_RAM_ADJ_3
*/
#define APU_RAM_ADJ_3 ( ( APU_BASEADDR ) + 0X000000FC )
#define APU_RAM_ADJ_3_L2_TAGECC_EMAS_SHIFT 29
#define APU_RAM_ADJ_3_L2_TAGECC_EMAS_WIDTH 1
#define APU_RAM_ADJ_3_L2_TAGECC_EMAS_MASK 0X20000000
#define APU_RAM_ADJ_3_L2_TAGECC_EMAW_SHIFT 27
#define APU_RAM_ADJ_3_L2_TAGECC_EMAW_WIDTH 2
#define APU_RAM_ADJ_3_L2_TAGECC_EMAW_MASK 0X18000000
#define APU_RAM_ADJ_3_L2_TAGECC_EMA_SHIFT 24
#define APU_RAM_ADJ_3_L2_TAGECC_EMA_WIDTH 3
#define APU_RAM_ADJ_3_L2_TAGECC_EMA_MASK 0X07000000
#define APU_RAM_ADJ_3_L2_TAG_EMAS_SHIFT 21
#define APU_RAM_ADJ_3_L2_TAG_EMAS_WIDTH 1
#define APU_RAM_ADJ_3_L2_TAG_EMAS_MASK 0X00200000
#define APU_RAM_ADJ_3_L2_TAG_EMAW_SHIFT 19
#define APU_RAM_ADJ_3_L2_TAG_EMAW_WIDTH 2
#define APU_RAM_ADJ_3_L2_TAG_EMAW_MASK 0X00180000
#define APU_RAM_ADJ_3_L2_TAG_EMA_SHIFT 16
#define APU_RAM_ADJ_3_L2_TAG_EMA_WIDTH 3
#define APU_RAM_ADJ_3_L2_TAG_EMA_MASK 0X00070000
#define APU_RAM_ADJ_3_L2_DATAECC_EMAS_SHIFT 13
#define APU_RAM_ADJ_3_L2_DATAECC_EMAS_WIDTH 1
#define APU_RAM_ADJ_3_L2_DATAECC_EMAS_MASK 0X00002000
#define APU_RAM_ADJ_3_L2_DATAECC_EMAW_SHIFT 11
#define APU_RAM_ADJ_3_L2_DATAECC_EMAW_WIDTH 2
#define APU_RAM_ADJ_3_L2_DATAECC_EMAW_MASK 0X00001800
#define APU_RAM_ADJ_3_L2_DATAECC_EMA_SHIFT 8
#define APU_RAM_ADJ_3_L2_DATAECC_EMA_WIDTH 3
#define APU_RAM_ADJ_3_L2_DATAECC_EMA_MASK 0X00000700
#define APU_RAM_ADJ_3_L2_DATA_EMAS_SHIFT 5
#define APU_RAM_ADJ_3_L2_DATA_EMAS_WIDTH 1
#define APU_RAM_ADJ_3_L2_DATA_EMAS_MASK 0X00000020
#define APU_RAM_ADJ_3_L2_DATA_EMAW_SHIFT 3
#define APU_RAM_ADJ_3_L2_DATA_EMAW_WIDTH 2
#define APU_RAM_ADJ_3_L2_DATA_EMAW_MASK 0X00000018
#define APU_RAM_ADJ_3_L2_DATA_EMA_SHIFT 0
#define APU_RAM_ADJ_3_L2_DATA_EMA_WIDTH 3
#define APU_RAM_ADJ_3_L2_DATA_EMA_MASK 0X00000007
/**
* Register: APU_XPD_REG0
*/
#define APU_XPD_REG0 ( ( APU_BASEADDR ) + 0X00000600 )
#define APU_XPD_REG0_PRE_LOAD_SHIFT 0
#define APU_XPD_REG0_PRE_LOAD_WIDTH 32
#define APU_XPD_REG0_PRE_LOAD_MASK 0XFFFFFFFF
/**
* Register: APU_XPD_REG1
*/
#define APU_XPD_REG1 ( ( APU_BASEADDR ) + 0X00000604 )
#define APU_XPD_REG1_EXPECTED_SHIFT 0
#define APU_XPD_REG1_EXPECTED_WIDTH 32
#define APU_XPD_REG1_EXPECTED_MASK 0XFFFFFFFF
/**
* Register: APU_XPD_CTRL0
*/
#define APU_XPD_CTRL0 ( ( APU_BASEADDR ) + 0X00000608 )
#define APU_XPD_CTRL0_DELAY_SPARE_SHIFT 25
#define APU_XPD_CTRL0_DELAY_SPARE_WIDTH 5
#define APU_XPD_CTRL0_DELAY_SPARE_MASK 0X3E000000
#define APU_XPD_CTRL0_CMP_SEL_SHIFT 24
#define APU_XPD_CTRL0_CMP_SEL_WIDTH 1
#define APU_XPD_CTRL0_CMP_SEL_MASK 0X01000000
#define APU_XPD_CTRL0_DELAY_CELL_TYPE_SHIFT 19
#define APU_XPD_CTRL0_DELAY_CELL_TYPE_WIDTH 5
#define APU_XPD_CTRL0_DELAY_CELL_TYPE_MASK 0X00F80000
#define APU_XPD_CTRL0_DELAY_VT_TYPE_SHIFT 17
#define APU_XPD_CTRL0_DELAY_VT_TYPE_WIDTH 2
#define APU_XPD_CTRL0_DELAY_VT_TYPE_MASK 0X00060000
#define APU_XPD_CTRL0_DELAY_VALUE_SHIFT 6
#define APU_XPD_CTRL0_DELAY_VALUE_WIDTH 11
#define APU_XPD_CTRL0_DELAY_VALUE_MASK 0X0001FFC0
#define APU_XPD_CTRL0_PATH_SEL_SHIFT 0
#define APU_XPD_CTRL0_PATH_SEL_WIDTH 6
#define APU_XPD_CTRL0_PATH_SEL_MASK 0X0000003F
/**
* Register: APU_XPD_CTRL1
*/
#define APU_XPD_CTRL1 ( ( APU_BASEADDR ) + 0X0000060C )
#define APU_XPD_CTRL1_CLK_SPARE_SHIFT 12
#define APU_XPD_CTRL1_CLK_SPARE_WIDTH 4
#define APU_XPD_CTRL1_CLK_SPARE_MASK 0X0000F000
#define APU_XPD_CTRL1_CLK_PHASE_SEL_SHIFT 10
#define APU_XPD_CTRL1_CLK_PHASE_SEL_WIDTH 2
#define APU_XPD_CTRL1_CLK_PHASE_SEL_MASK 0X00000C00
#define APU_XPD_CTRL1_CLK_VT_TYPE_SHIFT 8
#define APU_XPD_CTRL1_CLK_VT_TYPE_WIDTH 2
#define APU_XPD_CTRL1_CLK_VT_TYPE_MASK 0X00000300
#define APU_XPD_CTRL1_CLK_CELL_TYPE_SHIFT 6
#define APU_XPD_CTRL1_CLK_CELL_TYPE_WIDTH 2
#define APU_XPD_CTRL1_CLK_CELL_TYPE_MASK 0X000000C0
#define APU_XPD_CTRL1_CLK_INSERT_DLY_SHIFT 2
#define APU_XPD_CTRL1_CLK_INSERT_DLY_WIDTH 4
#define APU_XPD_CTRL1_CLK_INSERT_DLY_MASK 0X0000003C
#define APU_XPD_CTRL1_CLK_SEL_SHIFT 0
#define APU_XPD_CTRL1_CLK_SEL_WIDTH 2
#define APU_XPD_CTRL1_CLK_SEL_MASK 0X00000003
/**
* Register: APU_XPD_CTRL2
*/
#define APU_XPD_CTRL2 ( ( APU_BASEADDR ) + 0X00000614 )
#define APU_XPD_CTRL2_CTRL_SPARE_SHIFT 1
#define APU_XPD_CTRL2_CTRL_SPARE_WIDTH 2
#define APU_XPD_CTRL2_CTRL_SPARE_MASK 0X00000006
#define APU_XPD_CTRL2_ENABLE_SHIFT 0
#define APU_XPD_CTRL2_ENABLE_WIDTH 1
#define APU_XPD_CTRL2_ENABLE_MASK 0X00000001
/**
* Register: APU_XPD_CTRL3
*/
#define APU_XPD_CTRL3 ( ( APU_BASEADDR ) + 0X00000618 )
#define APU_XPD_CTRL3_DCYCLE_CNT_VALUE_SHIFT 3
#define APU_XPD_CTRL3_DCYCLE_CNT_VALUE_WIDTH 12
#define APU_XPD_CTRL3_DCYCLE_CNT_VALUE_MASK 0X00007FF8
#define APU_XPD_CTRL3_DCYCLE_HIGH_LOW_SHIFT 2
#define APU_XPD_CTRL3_DCYCLE_HIGH_LOW_WIDTH 1
#define APU_XPD_CTRL3_DCYCLE_HIGH_LOW_MASK 0X00000004
#define APU_XPD_CTRL3_DCYCLE_CNT_CLR_SHIFT 1
#define APU_XPD_CTRL3_DCYCLE_CNT_CLR_WIDTH 1
#define APU_XPD_CTRL3_DCYCLE_CNT_CLR_MASK 0X00000002
#define APU_XPD_CTRL3_DCYCLE_START_SHIFT 0
#define APU_XPD_CTRL3_DCYCLE_START_WIDTH 1
#define APU_XPD_CTRL3_DCYCLE_START_MASK 0X00000001
/**
* Register: APU_XPD_SOFT_RST
*/
#define APU_XPD_SOFT_RST ( ( APU_BASEADDR ) + 0X0000061C )
#define APU_XPD_SOFT_RST_CLK2_SHIFT 2
#define APU_XPD_SOFT_RST_CLK2_WIDTH 1
#define APU_XPD_SOFT_RST_CLK2_MASK 0X00000004
#define APU_XPD_SOFT_RST_CLK1_SHIFT 1
#define APU_XPD_SOFT_RST_CLK1_WIDTH 1
#define APU_XPD_SOFT_RST_CLK1_MASK 0X00000002
#define APU_XPD_SOFT_RST_CLK0_SHIFT 0
#define APU_XPD_SOFT_RST_CLK0_WIDTH 1
#define APU_XPD_SOFT_RST_CLK0_MASK 0X00000001
/**
* Register: APU_XPD_STAT
*/
#define APU_XPD_STAT ( ( APU_BASEADDR ) + 0X00000620 )
#define APU_XPD_STAT_CMP_RESULT_SHIFT 1
#define APU_XPD_STAT_CMP_RESULT_WIDTH 1
#define APU_XPD_STAT_CMP_RESULT_MASK 0X00000002
#define APU_XPD_STAT_CMP_DONE_SHIFT 0
#define APU_XPD_STAT_CMP_DONE_WIDTH 1
#define APU_XPD_STAT_CMP_DONE_MASK 0X00000001
#ifdef __cplusplus
}
#endif
#endif /* _PM_APU_H_ */

View file

@ -0,0 +1,152 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* Each PU client in the system have such file with definitions of
* masters in the subsystem and functions for getting informations
* about the master.
*********************************************************************/
#include "pm_client.h"
static const struct XPm_Ipi apu_ipi = {
.mask = IPI_APU_MASK,
.base = IPI_BASEADDR,
.buffer_base = IPI_BUFFER_APU_BASE,
};
static const struct XPm_Master pm_apu_0_master = {
.node_id = NODE_APU_0,
.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
.ipi = &apu_ipi,
};
static const struct XPm_Master pm_apu_1_master = {
.node_id = NODE_APU_1,
.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
.ipi = &apu_ipi,
};
static const struct XPm_Master pm_apu_2_master = {
.node_id = NODE_APU_2,
.pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK,
.ipi = &apu_ipi,
};
static const struct XPm_Master pm_apu_3_master = {
.node_id = NODE_APU_3,
.pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK,
.ipi = &apu_ipi,
};
/*
* Order in pm_master_all array must match cpu ids
*/
static const struct XPm_Master *const pm_masters_all[] = {
&pm_apu_0_master,
&pm_apu_1_master,
&pm_apu_2_master,
&pm_apu_3_master,
};
/**
* pm_get_master() - returns pointer to the master structure
* @cpuid: id of the cpu whose master struct pointer should be returned
*
* Return: pointer to a master structure if master is found, otherwise NULL
*/
const struct XPm_Master *pm_get_master(const uint32_t cpuid)
{
if (cpuid >=0 && PM_ARRAY_SIZE(pm_masters_all)) {
return pm_masters_all[cpuid];
}
return NULL;
}
/**
* pm_get_master_by_node() - returns pointer to the master structure
* @nid: ndoe id of the cpu master
*
* Return: pointer to a master structure if master is found, otherwise NULL
*/
const struct XPm_Master *pm_get_master_by_node(const enum XPmNodeId nid)
{
uint8_t i;
for (i = 0; i < PM_ARRAY_SIZE(pm_masters_all); i++) {
if (nid == pm_masters_all[i]->node_id) {
return pm_masters_all[i];
}
}
return NULL;
}
static uint32_t pm_get_cpuid(const enum XPmNodeId node)
{
uint32_t i;
for (i = 0; i < PM_ARRAY_SIZE(pm_masters_all); i++) {
if (pm_masters_all[i]->node_id == node) {
return i;
}
}
return UNDEFINED_CPUID;
}
const enum XPmNodeId subsystem_node = NODE_APU;
const struct XPm_Master *primary_master = &pm_apu_0_master;
void XPm_ClientSuspend(const struct XPm_Master *const master)
{
/* Disable interrupts at processor level */
pm_disable_int();
/* Set powerdown request */
pm_write(MASTER_PWRCTL, pm_read(MASTER_PWRCTL) | master->pwrdn_mask);
}
void XPm_ClientAbortSuspend()
{
/* Enable interrupts at processor level */
pm_enable_int();
/* Clear powerdown request */
pm_write(MASTER_PWRCTL, pm_read(MASTER_PWRCTL) & ~primary_master->pwrdn_mask);
}
void XPm_ClientWakeup(const struct XPm_Master *const master)
{
uint32_t cpuid = pm_get_cpuid(master->node_id);
if (UNDEFINED_CPUID != cpuid) {
uint32_t val = pm_read(MASTER_PWRCTL);
val &= ~(master->pwrdn_mask);
pm_write(MASTER_PWRCTL, val);
}
}

View file

@ -0,0 +1,95 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* File is specific for each PU instance and must exist in order to
* port Power Management code for some new PU.
* Contains PU specific macros and macros to be defined depending on
* the execution environment.
*********************************************************************/
#ifndef _PM_CLIENT_H_
#define _PM_CLIENT_H_
#include <xil_exception.h>
#include <xil_io.h>
#include "pm_apu.h"
#include "pm_defs.h"
#include "pm_common.h"
#define MASTER_PWRCTL APU_PWRCTL
#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 0x00000001U
#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 0x00000002U
#define APU_2_PWRCTL_CPUPWRDWNREQ_MASK 0x00000004U
#define APU_3_PWRCTL_CPUPWRDWNREQ_MASK 0x00000008U
#define IPI_APU_MASK 0x00000001U
#define IPI_TRIG_OFFSET 0x00000000
#define IPI_OBS_OFFSET 0x00000004
#define UNDEFINED_CPUID (~0)
#define pm_read(addr) Xil_In32(addr)
#define pm_write(addr, value) Xil_Out32(addr, value)
#define pm_enable_int() Xil_ExceptionEnable()
#define pm_disable_int() Xil_ExceptionDisable()
#define pm_print(MSG, ...) xil_printf("APU: "MSG,##__VA_ARGS__)
#define pm_this_cpuid() 0U
/* Conditional debugging prints */
#ifdef DEBUG_MODE
#define pm_dbg(MSG, ...) \
do { \
pm_print(MSG,##__VA_ARGS__); \
} while (0)
#else
#define pm_dbg(MSG, ...) {}
#endif
#ifndef bool
#define bool uint8_t
#define true 1U
#define false 0U
#endif
void XPm_ClientSuspend(const struct XPm_Master *const master);
void XPm_ClientAbortSuspend();
void XPm_ClientWakeup(const struct XPm_Master *const master);
/* Do not modify below this line */
extern const enum XPmNodeId subsystem_node;
extern const struct XPm_Master *primary_master;
#endif /* _PM_CLIENT_H_ */

View file

@ -0,0 +1,35 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxilpm.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner xilpm_libs clean
%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $<
banner:
echo "Compiling xilpm library"
xilpm_libs: ${OBJECTS}
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS}
include:
echo "Include files for this library have already been copied."
clean:
rm -rf ${OBJECTS}

View file

@ -0,0 +1,455 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
#include "pm_client.h"
#include "pm_common.h"
#include "pm_api_sys.h"
#include "pm_ipi_buffer.h"
/**
* Assigning of argument values into array elements.
* pause and pm_dbg are used for debugging and should be removed in
* final version.
*/
#define PACK_PAYLOAD(pl, arg0, arg1, arg2, arg3, arg4) \
pl[0] = (uint32_t)arg0; \
pl[1] = (uint32_t)arg1; \
pl[2] = (uint32_t)arg2; \
pl[3] = (uint32_t)arg3; \
pl[4] = (uint32_t)arg4; \
pm_dbg("%s(%d, %d, %d, %d)\n", __func__, arg1, arg2, arg3, arg4);
/**
* pm_get_boot_status() - checks for reason of boot
*
* Function returns information about the boot reason.
* If the boot is not a system startup but a resume,
* power down request bitfield for this processor will be cleared.
*
* @return Returns processor boot status
*/
enum XPmBootStatus XPm_GetBootStatus()
{
uint32_t pwrdn_req = pm_read(MASTER_PWRCTL);
if (0 != (pwrdn_req & primary_master->pwrdn_mask)) {
pm_write(MASTER_PWRCTL, pwrdn_req & (~primary_master->pwrdn_mask));
return PM_RESUME;
} else {
return PM_INITIAL_BOOT;
}
}
/**
* pm_ipi_wait() - wait for pmu to handle request
* @master master which is waiting for PMU to handle request
*/
static enum XPmStatus pm_ipi_wait(const struct XPm_Master *const master)
{
volatile uint32_t status = 1;
/* Wait until previous interrupt is handled by PMU */
while (status) {
status = pm_read(master->ipi->base + IPI_OBS_OFFSET)
& IPI_PMU_PM_INT_MASK;
/* TODO: 1) Use timer to add delay between read attempts */
/* TODO: 2) Return PM_RET_ERR_TIMEOUT if this times out */
}
return PM_RET_SUCCESS;
}
/**
* pm_ipi_send() - Sends IPI request to the PMU
* @master Pointer to the master who is initiating request
* @payload API id and call arguments to be written in IPI buffer
*
* @return Returns status, either success or error+reason
*/
static enum XPmStatus pm_ipi_send(const struct XPm_Master *const master,
uint32_t payload[PAYLOAD_ARG_CNT])
{
uint32_t i;
uint32_t offset = 0;
uint32_t buffer_base = master->ipi->buffer_base
+ IPI_BUFFER_TARGET_PMU_OFFSET
+ IPI_BUFFER_REQ_OFFSET;
/* Wait until previous interrupt is handled by PMU */
pm_ipi_wait(master);
/* Write payload into IPI buffer */
for (i = 0; i < PAYLOAD_ARG_CNT; i++) {
pm_write(buffer_base + offset, payload[i]);
offset += PAYLOAD_ARG_SIZE;
}
/* Generate IPI to PMU */
pm_write(master->ipi->base + IPI_TRIG_OFFSET, IPI_PMU_PM_INT_MASK);
return PM_RET_SUCCESS;
}
/**
* pm_ipi_buff_read32() - Reads IPI response after PMU has handled interrupt
* @master Pointer to the master who is waiting and reading response
* @value Used to return value from 2nd IPI buffer element (optional)
*
* @return Returns status, either success or error+reason
*/
static enum XPmStatus pm_ipi_buff_read32(const struct XPm_Master *const master,
uint32_t *value)
{
uint32_t buffer_base = master->ipi->buffer_base
+ IPI_BUFFER_TARGET_PMU_OFFSET
+ IPI_BUFFER_RESP_OFFSET;
volatile uint32_t status = 1;
/* Wait until current IPI interrupt is handled by PMU */
while (status) {
status = pm_read(master->ipi->base + IPI_OBS_OFFSET) & IPI_PMU_PM_INT_MASK;
/* TODO: 1) Use timer to add delay between read attempts */
/* TODO: 2) Return PM_RET_ERR_TIMEOUT if this times out */
}
/*
* Read response from IPI buffer
* buf-0: success or error+reason
* buf-1: value
* buf-2: unused
* buf-3: unused
*/
if (NULL != value)
*value = pm_read(buffer_base + PAYLOAD_ARG_SIZE);
return pm_read(buffer_base);
}
/**
* pm_self_suspend() - PM call for master to suspend itself
* @node Node id of the master or subsystem
* @latency Requested maximum wakeup latency (not supported)
* @state Requested state (not supported)
*
* This is a blocking call, it will return only once PMU has responded
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_SelfSuspend(const enum XPmNodeId nid,
const uint32_t latency,
const uint8_t state)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
const struct XPm_Master *master = pm_get_master_by_node(nid);
if (NULL == master) {
/*
* If a subsystem node ID (APU or RPU) was passed then
* the master to be used is the primary master.
* E.g. for the APU the primary master is APU0
*/
if (subsystem_node == nid) {
master = primary_master;
} else {
return PM_RET_ERROR_ARGS;
}
}
/*
* Do client specific suspend operations
* (e.g. disable interrupts and set powerdown request bit)
*/
XPm_ClientSuspend(master);
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_SELF_SUSPEND, nid, latency, state, 0);
ret = pm_ipi_send(master, payload);
if (PM_RET_SUCCESS != ret)
return ret;
/* Wait for PMU to finish handling request */
return pm_ipi_wait(master);
}
/**
* pm_req_suspend() - PM call to request for another PU or subsystem to
* be suspended gracefully.
* @target Node id of the targeted PU or subsystem
* @ack Flag to specify whether acknowledge is requested
* @latency Requested wakeup latency (not supported)
* @state Requested state (not supported)
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_ReqSuspend(const enum XPmNodeId target,
const enum XPmRequestAck ack,
const uint32_t latency, const uint8_t state)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_REQ_SUSPEND, target, ack, latency, state);
ret = pm_ipi_send(primary_master, payload);
if ((PM_RET_SUCCESS == ret) && (REQ_ACK_BLOCKING == ack))
return pm_ipi_buff_read32(primary_master, NULL);
else
return ret;
}
/**
* pm_req_wakeup() - PM call for master to wake up selected master or subsystem
* @node Node id of the master or subsystem
* @ack Flag to specify whether acknowledge requested
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_ReqWakeUp(const enum XPmNodeId target,
const enum XPmRequestAck ack)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
const struct XPm_Master *master = pm_get_master_by_node(target);
XPm_ClientWakeup(master);
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_REQ_WAKEUP, target, ack, 0, 0);
ret = pm_ipi_send(primary_master, payload);
if ((PM_RET_SUCCESS == ret) && (REQ_ACK_BLOCKING == ack))
return pm_ipi_buff_read32(primary_master, NULL);
else
return ret;
}
/**
* pm_force_powerdown() - PM call to request for another PU or subsystem to
* be powered down forcefully
* @target Node id of the targeted PU or subsystem
* @ack Flag to specify whether acknowledge is requested
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_ForcePowerDown(const enum XPmNodeId target,
const enum XPmRequestAck ack)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_FORCE_POWERDOWN, target, ack, 0, 0);
ret = pm_ipi_send(primary_master, payload);
if ((PM_RET_SUCCESS == ret) && (REQ_ACK_BLOCKING == ack))
return pm_ipi_buff_read32(primary_master, NULL);
else
return ret;
}
/**
* pm_abort_suspend() - PM call to announce that a prior suspend request
* is to be aborted.
* @reason Reason for the abort
*
* Calling PU expects the PMU to abort the initiated suspend procedure.
* This is a non-blocking call without any acknowledge.
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_AbortSuspend(const enum XPmAbortReason reason)
{
enum XPmStatus status;
uint32_t payload[PAYLOAD_ARG_CNT];
/*
* Do client specific abort suspend operations
* (e.g. enable interrupts and clear powerdown request bit)
*/
XPm_ClientAbortSuspend();
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_ABORT_SUSPEND, reason, primary_master->node_id, 0, 0);
status = pm_ipi_send(primary_master, payload);
if (PM_RET_SUCCESS == status)
/* Wait for PMU to finish handling request */
status = pm_ipi_wait(primary_master);
return status;
}
/**
* pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
* @target Node id of the targeted PU or subsystem
* @wkup_node Node id of the wakeup peripheral
* @enable Enable or disable the specified peripheral as wake source
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_SetWakeUpSource(const enum XPmNodeId target,
const enum XPmNodeId wkup_node,
const uint8_t enable)
{
uint32_t payload[PAYLOAD_ARG_CNT];
PACK_PAYLOAD(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node, enable, 0);
return pm_ipi_send(primary_master, payload);
}
/**
* pm_system_shutdown() - PM call to request a system shutdown or restart
* @restart Shutdown or restart? 0 for shutdown, 1 for restart
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_SystemShutdown(const uint8_t restart)
{
uint32_t payload[PAYLOAD_ARG_CNT];
PACK_PAYLOAD(payload, PM_SYSTEM_SHUTDOWN, restart, 0, 0, 0);
return pm_ipi_send(primary_master, payload);
}
/* APIs for managing PM slaves: */
/**
* pm_req_node() - PM call to request a node with specifc capabilities
* @node Node id of the slave
* @capabilities Requested capabilities of the slave
* @qos Quality of service (not supported)
* @ack Flag to specify whether acknowledge is requested
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_ReqNode(const enum XPmNodeId node,
const uint32_t capabilities,
const uint32_t qos,
const enum XPmRequestAck ack)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
PACK_PAYLOAD(payload, PM_REQ_NODE, node, capabilities, qos, ack);
ret = pm_ipi_send(primary_master, payload);
if ((PM_RET_SUCCESS == ret) && (REQ_ACK_BLOCKING == ack))
return pm_ipi_buff_read32(primary_master, NULL);
else
return ret;
}
/**
* pm_set_requirement() - PM call to set requirement for PM slaves
* @node Node id of the slave
* @capabilities Requested capabilities of the slave
* @qos Quality of service (not supported)
* @ack Flag to specify whether acknowledge is requested
*
* This API function is to be used for slaves a PU already has requested
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_SetRequirement(const enum XPmNodeId nid,
const uint32_t capabilities,
const uint32_t qos,
const enum XPmRequestAck ack)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
PACK_PAYLOAD(payload, PM_SET_REQUIREMENT, nid, capabilities, qos, ack);
ret = pm_ipi_send(primary_master, payload);
if ((PM_RET_SUCCESS == ret) && (REQ_ACK_BLOCKING == ack))
return pm_ipi_buff_read32(primary_master, NULL);
else
return ret;
}
/**
* pm_release_node() - PM call to release a node
* @node Node id of the slave
* @latency Requested maximum wakeup latency
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_ReleaseNode(const enum XPmNodeId node,
const uint32_t latency)
{
uint32_t payload[PAYLOAD_ARG_CNT];
PACK_PAYLOAD(payload, PM_RELEASE_NODE, node, latency, 0, 0);
return pm_ipi_send(primary_master, payload);
}
/**
* pm_set_max_latency() - PM call to set wakeup latency requirements
* @node Node id of the slave
* @latency Requested maximum wakeup latency
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_SetMaxLatency(const enum XPmNodeId node,
const uint32_t latency)
{
uint32_t payload[PAYLOAD_ARG_CNT];
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_SET_MAX_LATENCY, node, latency, 0, 0);
return pm_ipi_send(primary_master, payload);
}
/* Miscellaneous API functions */
/**
* pm_get_api_version() - Get version number of PMU PM firmware
* @version Returns 32-bit version number of PMU Power Management Firmware
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_GetApiVersion(uint32_t *version)
{
enum XPmStatus ret;
uint32_t payload[PAYLOAD_ARG_CNT];
/* Send request to the PMU */
PACK_PAYLOAD(payload, PM_GET_API_VERSION, 0, 0, 0, 0);
ret = pm_ipi_send(primary_master, payload);
if (PM_RET_SUCCESS != ret)
return ret;
/* Return result from IPI return buffer */
return pm_ipi_buff_read32(primary_master, version);
}
/**
* pm_get_node_status() - PM call to request a node's current power state
* @node Node id of the slave
*
* @return Returns status, either success or error+reason
*/
enum XPmStatus XPm_GetNodeStatus(const enum XPmNodeId node)
{
/* TODO: Add power state argument!! */
uint32_t payload[PAYLOAD_ARG_CNT];
PACK_PAYLOAD(payload, PM_GET_NODE_STATUS, node, 0, 0, 0);
return pm_ipi_send(primary_master, payload);
}

View file

@ -0,0 +1,91 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
#ifndef _PM_API_SYS_H_
#define _PM_API_SYS_H_
#include <stdint.h>
#include "pm_defs.h"
enum XPmBootStatus XPm_GetBootStatus();
/**********************************************************
* System-level API function declarations
**********************************************************/
enum XPmStatus XPm_ReqSuspend(const enum XPmNodeId node,
const enum XPmRequestAck ack,
const uint32_t latency,
const uint8_t state);
enum XPmStatus XPm_SelfSuspend(const enum XPmNodeId node,
const uint32_t latency,
const uint8_t state);
enum XPmStatus XPm_ForcePowerDown(const enum XPmNodeId node,
const enum XPmRequestAck ack);
enum XPmStatus XPm_AbortSuspend(const enum XPmAbortReason reason);
enum XPmStatus XPm_ReqWakeUp(const enum XPmNodeId node,
const enum XPmRequestAck ack);
enum XPmStatus XPm_SetWakeUpSource(const enum XPmNodeId target,
const enum XPmNodeId wkup_node,
const uint8_t enable);
enum XPmStatus XPm_SystemShutdown(const uint8_t restart);
/* API functions for managing PM Slaves */
enum XPmStatus XPm_ReqNode(const enum XPmNodeId node,
const uint32_t capabilities,
const uint32_t qos,
const enum XPmRequestAck ack);
enum XPmStatus XPm_ReleaseNode(const enum XPmNodeId node,
const uint32_t latency);
enum XPmStatus XPm_SetRequirement(const enum XPmNodeId node,
const uint32_t capabilities,
const uint32_t qos,
const enum XPmRequestAck ack);
enum XPmStatus XPm_SetMaxLatency(const enum XPmNodeId node,
const uint32_t latency);
/* Miscellaneous API functions */
enum XPmStatus XPm_GetApiVersion(uint32_t *version);
enum XPmStatus XPm_GetNodeStatus(const enum XPmNodeId node);
#endif /* _PM_API_SYS_H_ */

View file

@ -0,0 +1,78 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/**********************************************************************
* CONTENT
* Definitions of commonly used macros and data types needed for
* PU Power Management. This file should be common for all PU's.
*********************************************************************/
#ifndef _PM_COMMON_H_
#define _PM_COMMON_H_
#include "pm_ipi.h"
#include "pm_ipi_buffer.h"
#include "pm_defs.h"
#define DEBUG_MODE
#define PM_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#define PAYLOAD_ARG_CNT 5U
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
/* Power Management IPI interrupt number */
#define PM_INT_NUM 0
#define IPI_PMU_PM_INT_BASE (IPI_PMU_0_TRIG + (PM_INT_NUM * 0x1000))
#define IPI_PMU_PM_INT_MASK (IPI_APU_ISR_PMU_0_MASK << PM_INT_NUM)
#if (PM_INT_NUM < 0 || PM_INT_NUM > 3)
#error PM_INT_NUM value out of range
#endif
struct XPm_Ipi {
const uint32_t mask;
const uint32_t base;
const uint32_t buffer_base;
};
struct XPm_Master {
const enum XPmNodeId node_id;
const uint32_t pwrdn_mask;
const struct XPm_Ipi *const ipi;
};
const enum XPmNodeId pm_get_subsystem_node(void);
const struct XPm_Master *pm_get_master(const uint32_t cpuid);
const struct XPm_Master *pm_get_master_by_node(const enum XPmNodeId nid);
#endif /* _PM_COMMON_H_ */

View file

@ -0,0 +1,196 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
#ifndef PM_DEFS_H_
#define PM_DEFS_H_
/*********************************************************************
* Macro definitions
********************************************************************/
/*
* Version number is a 32bit value, like:
* (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
*/
#define PM_VERSION_MAJOR 0
#define PM_VERSION_MINOR 1
#define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
/* Capabilities for RAM */
#define PM_CAP_ACCESS 0x1U
#define PM_CAP_CONTEXT 0x2U
#define MAX_LATENCY (~0U)
#define MAX_QOS 100U
/*********************************************************************
* Enum definitions
********************************************************************/
enum XPmApiId {
/* Miscellaneous API functions: */
PM_GET_API_VERSION = 1, /* Do not change or move */
PM_SET_CONFIGURATION = 2,
PM_GET_NODE_STATUS = 3,
PM_GET_OP_CHARACTERISTIC = 4,
PM_REGISTER_NOTIFIER = 5,
/* API for suspending of PUs: */
PM_REQ_SUSPEND = 6,
PM_SELF_SUSPEND = 7,
PM_FORCE_POWERDOWN = 8,
PM_ABORT_SUSPEND = 9,
PM_REQ_WAKEUP = 10,
PM_SET_WAKEUP_SOURCE = 11,
PM_SYSTEM_SHUTDOWN = 12,
/* API for managing PM slaves: */
PM_REQ_NODE = 13,
PM_RELEASE_NODE = 14,
PM_SET_REQUIREMENT = 15,
PM_SET_MAX_LATENCY = 16,
/* Direct control API functions: */
PM_CLOCK_REQUEST = 17,
PM_CLOCK_RELEASE = 18,
PM_CLOCK_SET_RATE = 19,
PM_CLOCK_GET_RATE = 20,
PM_CLOCK_GET_RATE_INFO = 21,
PM_RESET_ASSERT = 22,
PM_RESET_GET_STATUS = 23,
PM_MMIO_WRITE = 24,
PM_MMIO_READ = 25,
};
#define PM_API_MIN 1
#define PM_API_MAX 25
enum XPmApiCbId {
PM_INIT_SUSPEND_CB = 30,
PM_ACKNOWLEDGE_CB,
PM_NOTIFY_CB,
};
enum XPmNodeId {
NODE_UNKNOWN = 0,
NODE_APU,
NODE_APU_0,
NODE_APU_1,
NODE_APU_2,
NODE_APU_3,
NODE_RPU,
NODE_RPU_0,
NODE_RPU_1,
NODE_PL,
NODE_FPD,
NODE_OCM_BANK_0,
NODE_OCM_BANK_1,
NODE_OCM_BANK_2,
NODE_OCM_BANK_3,
NODE_TCM_0_A,
NODE_TCM_0_B,
NODE_TCM_1_A,
NODE_TCM_1_B,
NODE_L2,
NODE_GPU_PP_0,
NODE_GPU_PP_1,
NODE_USB_0,
NODE_USB_1,
NODE_TTC_0,
};
enum XPmRequestAck {
REQ_ACK_NO = 1,
REQ_ACK_BLOCKING = 2,
REQ_ACK_CB_STANDARD = 3,
REQ_ACK_CB_ERROR = 4,
};
enum XPmAbortReason {
ABORT_REASON_WKUP_EVENT = 100,
ABORT_REASON_PU_BUSY,
ABORT_REASON_NO_PWRDN,
ABORT_REASON_UNKNOWN,
};
enum XPmSuspendReason {
SUSPEND_REASON_PU_REQ = 201,
SUSPEND_REASON_ALERT,
SUSPEND_REASON_SYS_SHUTDOWN,
};
enum XPmRamState {
PM_RAM_STATE_OFF = 1,
PM_RAM_STATE_RETENTION,
PM_RAM_STATE_ON,
};
enum XPmOpCharType {
PM_OPCHAR_TYPE_POWER = 1,
PM_OPCHAR_TYPE_ENERGY = 2,
PM_OPCHAR_TYPE_TEMP = 3,
};
/**
* @PM_RET_SUCCESS: success
* @PM_RET_ERROR_ARGS: illegal arguments provided
* @PM_RET_ERROR_ACCESS: access rights violation
* @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU
* @PM_RET_ERROR_NOTSUPPORTED: feature not supported
* @PM_RET_ERROR_PROC: node is not a processor node
* @PM_RET_ERROR_API_ID: illegal API ID
* @PM_RET_ERROR_OTHER: other error
*/
enum XPmStatus {
PM_RET_SUCCESS = 0,
PM_RET_ERROR_ARGS = 1,
PM_RET_ERROR_ACCESS = 2,
PM_RET_ERROR_TIMEOUT = 3,
PM_RET_ERROR_NOTSUPPORTED = 4,
PM_RET_ERROR_PROC = 5,
PM_RET_ERROR_API_ID = 6,
PM_RET_ERROR_FAILURE = 7,
PM_RET_ERROR_COMMUNIC = 8,
PM_RET_ERROR_DOUBLEREQ = 9,
PM_RET_ERROR_OTHER = 25,
};
/**
* @PM_INITIAL_BOOT: boot is a fresh system startup
* @PM_RESUME: boot is a resume
* @PM_BOOT_ERROR: error, boot cause cannot be identified
*/
enum XPmBootStatus {
PM_INITIAL_BOOT,
PM_RESUME,
PM_BOOT_ERROR,
};
#endif /* PM_DEFS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
#ifndef PM_IPI_BUFFER_H_
#define PM_IPI_BUFFER_H_
#define IPI_BUFFER_BASEADDR 0xFF990000U
#define IPI_BUFFER_RPU_0_BASE (IPI_BUFFER_BASEADDR + 0x0U)
#define IPI_BUFFER_RPU_1_BASE (IPI_BUFFER_BASEADDR + 0x200U)
#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U)
#define IPI_BUFFER_PL_0_BASE (IPI_BUFFER_BASEADDR + 0x600U)
#define IPI_BUFFER_PL_1_BASE (IPI_BUFFER_BASEADDR + 0x800U)
#define IPI_BUFFER_PL_2_BASE (IPI_BUFFER_BASEADDR + 0xA00U)
#define IPI_BUFFER_PL_3_BASE (IPI_BUFFER_BASEADDR + 0xC00U)
#define IPI_BUFFER_PMU_BASE (IPI_BUFFER_BASEADDR + 0xE00U)
#define IPI_BUFFER_TARGET_RPU_0_OFFSET 0x0U
#define IPI_BUFFER_TARGET_RPU_1_OFFSET 0x40U
#define IPI_BUFFER_TARGET_APU_OFFSET 0x80U
#define IPI_BUFFER_TARGET_PL_0_OFFSET 0xC0U
#define IPI_BUFFER_TARGET_PL_1_OFFSET 0x100U
#define IPI_BUFFER_TARGET_PL_2_OFFSET 0x140U
#define IPI_BUFFER_TARGET_PL_3_OFFSET 0x180U
#define IPI_BUFFER_TARGET_PMU_OFFSET 0x1C0U
#define IPI_BUFFER_REQ_OFFSET 0x0U
#define IPI_BUFFER_RESP_OFFSET 0x20U
#endif

View file

@ -0,0 +1,142 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* Each PU client in the system have such file with definitions of
* masters in the subsystem and functions for getting informations
* about the master.
*********************************************************************/
#include "pm_client.h"
static const struct XPm_Ipi rpu_0_ipi = {
.mask = IPI_RPU_MASK,
.base = IPI_BASEADDR,
.buffer_base = IPI_BUFFER_RPU_0_BASE,
};
static const struct XPm_Master pm_rpu_0_master = {
.node_id = NODE_RPU_0,
.pwrdn_mask = RPU_RPU_0_PWRDWN_EN_MASK,
.ipi = &rpu_0_ipi,
};
#if 0
static const struct XPm_Master pm_rpu_1_master = {
.node_id = NODE_APU_1,
.pwrdn_mask = RPU_RPU_0_PWRDWN_EN_MASK,
.ipi = &rpu_0_ipi,
};
#endif
/*
* Order in pm_master_all array must match cpu ids
*/
static const struct XPm_Master *const pm_masters_all[] = {
&pm_rpu_0_master,
#if 0
&pm_rpu_1_master,
#endif
};
/**
* pm_get_master() - returns pointer to the master structure
* @cpuid: id of the cpu whose master struct pointer should be returned
*
* Return: pointer to a master structure if master is found, otherwise NULL
*/
const struct XPm_Master *pm_get_master(const uint32_t cpuid)
{
if (cpuid >=0 && PM_ARRAY_SIZE(pm_masters_all)) {
return pm_masters_all[cpuid];
}
return NULL;
}
/**
* pm_get_master_by_node() - returns pointer to the master structure
* @nid: ndoe id of the cpu master
*
* Return: pointer to a master structure if master is found, otherwise NULL
*/
const struct XPm_Master *pm_get_master_by_node(const enum XPmNodeId nid)
{
uint8_t i;
for (i = 0; i < PM_ARRAY_SIZE(pm_masters_all); i++) {
if (nid == pm_masters_all[i]->node_id) {
return pm_masters_all[i];
}
}
return NULL;
}
static uint32_t pm_get_cpuid(const enum XPmNodeId node)
{
uint32_t i;
for (i = 0; i < PM_ARRAY_SIZE(pm_masters_all); i++) {
if (pm_masters_all[i]->node_id == node) {
return i;
}
}
return UNDEFINED_CPUID;
}
const enum XPmNodeId subsystem_node = NODE_RPU;
const struct XPm_Master *primary_master = &pm_rpu_0_master;
void XPm_ClientSuspend(const struct XPm_Master *const master)
{
/* Disable interrupts at processor level */
pm_disable_int();
/* Set powerdown request */
pm_write(MASTER_PWRCTL, pm_read(MASTER_PWRCTL) | master->pwrdn_mask);
}
void XPm_ClientAbortSuspend()
{
/* Enable interrupts at processor level */
pm_enable_int();
/* Clear powerdown request */
pm_write(MASTER_PWRCTL, pm_read(MASTER_PWRCTL) & ~primary_master->pwrdn_mask);
}
void XPm_ClientWakeup(const struct XPm_Master *const master)
{
uint32_t cpuid = pm_get_cpuid(master->node_id);
if (UNDEFINED_CPUID != cpuid) {
uint32_t val = pm_read(MASTER_PWRCTL);
val &= ~(master->pwrdn_mask);
pm_write(MASTER_PWRCTL, val);
}
}

View file

@ -0,0 +1,90 @@
/******************************************************************************
*
* Copyright (C) 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.
*
******************************************************************************/
/*********************************************************************
* CONTENT
* File is specific for each PU instance and must exist in order to
* port Power Management code for some new PU.
* Contains PU specific macros and macros to be defined depending on
* the execution environment.
*********************************************************************/
#ifndef _PM_CLIENT_H_
#define _PM_CLIENT_H_
#include <xil_exception.h>
#include <xil_io.h>
#include "pm_rpu.h"
#include "pm_defs.h"
#include "pm_common.h"
#define MASTER_PWRCTL RPU_RPU_0_PWRDWN
#define IPI_RPU_MASK 0x00000100U
#define IPI_TRIG_OFFSET 0x00010000
#define IPI_OBS_OFFSET 0x00010004
#define UNDEFINED_CPUID (~0)
#define pm_read(addr) Xil_In32(addr)
#define pm_write(addr, value) Xil_Out32(addr, value)
#define pm_enable_int() Xil_ExceptionEnable()
#define pm_disable_int() Xil_ExceptionDisable()
#define pm_print(MSG, ...) xil_printf("RPU: "MSG,##__VA_ARGS__)
#define pm_this_cpuid() 0U
/* Conditional debugging prints */
#ifdef DEBUG_MODE
#define pm_dbg(MSG, ...) \
do { \
pm_print(MSG,##__VA_ARGS__); \
} while (0)
#else
#define pm_dbg(MSG, ...) {}
#endif
#ifndef bool
#define bool uint8_t
#define true 1U
#define false 0U
#endif
void XPm_ClientSuspend(const struct XPm_Master *const master);
void XPm_ClientAbortSuspend();
void XPm_ClientWakeup(const struct XPm_Master *const master);
/* Do not modify below this line */
extern const enum XPmNodeId subsystem_node;
extern const struct XPm_Master *primary_master;
#endif /* _PM_CLIENT_H_ */

File diff suppressed because it is too large Load diff