Browse Source

xilinx: versal: Add PSCI APIs for suspend/resume

Add following APIs in plat_psci to support suspend resume:
- versal_pwr_domain_off
- versal_pwr_domain_suspend
- versal_pwr_domain_suspend_finish
- versal_validate_power_state
- versal_get_sys_suspend_power_state

Signed-off-by: Tejas Patel <tejas.patel@xilinx.com>
Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: Jolly Shah <jolly.shah@xilinx.com>
Change-Id: Ife908a45f32e2037c9c19e13211a8e4b373b8342
pull/1937/head
Tejas Patel 6 years ago
committed by Jolly Shah
parent
commit
5a8ffeabf9
  1. 2
      plat/xilinx/versal/aarch64/versal_common.c
  2. 4
      plat/xilinx/versal/bl31_versal_setup.c
  3. 2
      plat/xilinx/versal/include/plat_private.h
  4. 2
      plat/xilinx/versal/include/platform_def.h
  5. 10
      plat/xilinx/versal/include/versal_def.h
  6. 142
      plat/xilinx/versal/plat_psci.c
  7. 9
      plat/xilinx/versal/platform.mk
  8. 7
      plat/xilinx/versal/pm_service/pm_defs.h

2
plat/xilinx/versal/aarch64/versal_common.c

@ -22,6 +22,8 @@ const mmap_region_t plat_versal_mmap[] = {
MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(FPD_MAINCCI_BASE, FPD_MAINCCI_SIZE, MT_DEVICE | MT_RW |
MT_SECURE),
{ 0 }
};

4
plat/xilinx/versal/bl31_versal_setup.c

@ -6,6 +6,7 @@
#include <assert.h>
#include <errno.h>
#include <plat_arm.h>
#include <plat_private.h>
#include <bl31/bl31.h>
#include <common/bl_common.h>
@ -102,6 +103,9 @@ void bl31_plat_runtime_setup(void)
*/
void bl31_plat_arch_setup(void)
{
plat_arm_interconnect_init();
plat_arm_interconnect_enter_coherency();
const mmap_region_t bl_regions[] = {
MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
MT_MEMORY | MT_RW | MT_SECURE),

2
plat/xilinx/versal/include/plat_private.h

@ -18,6 +18,8 @@ void plat_versal_gic_init(void);
void plat_versal_gic_cpuif_enable(void);
void plat_versal_gic_cpuif_disable(void);
void plat_versal_gic_pcpu_init(void);
void plat_versal_gic_save(void);
void plat_versal_gic_resume(void);
unsigned int versal_calc_core_pos(u_register_t mpidr);

2
plat/xilinx/versal/include/platform_def.h

@ -75,7 +75,7 @@
******************************************************************************/
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
#define MAX_MMAP_REGIONS 7
#define MAX_MMAP_REGIONS 8
#define MAX_XLAT_TABLES 5
#define CACHE_WRITEBACK_SHIFT 6

10
plat/xilinx/versal/include/versal_def.h

@ -55,6 +55,13 @@
******************************************************************************/
#define VERSAL_IRQ_SEC_PHY_TIMER 29
/*******************************************************************************
* CCI-400 related constants
******************************************************************************/
#define PLAT_ARM_CCI_BASE 0xFD000000
#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4
#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5
/*******************************************************************************
* UART related constants
******************************************************************************/
@ -97,6 +104,9 @@
#define CRF_RST_APU_ACPU_RESET (1 << 0)
#define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10)
#define FPD_MAINCCI_BASE 0xFD000000
#define FPD_MAINCCI_SIZE 0x00100000
/* APU registers and bitfields */
#define FPD_APU_BASE 0xFD5C0000
#define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20)

142
plat/xilinx/versal/plat_psci.c

@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <plat_arm.h>
#include <plat_private.h>
#include <pm_common.h>
#include <common/debug.h>
@ -38,6 +40,71 @@ static int versal_pwr_domain_on(u_register_t mpidr)
return PSCI_E_SUCCESS;
}
/**
* versal_pwr_domain_suspend() - This function sends request to PMC to suspend
* core.
*
* @target_state Targated state
*/
static void versal_pwr_domain_suspend(const psci_power_state_t *target_state)
{
unsigned int state;
unsigned int cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]);
plat_versal_gic_cpuif_disable();
plat_versal_gic_save();
state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
/* Send request to PMC to suspend this core */
pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry);
/* APU is to be turned off */
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
/* disable coherency */
plat_arm_interconnect_exit_coherency();
}
}
/**
* versal_pwr_domain_suspend_finish() - This function performs actions to finish
* suspend procedure.
*
* @target_state Targated state
*/
static void versal_pwr_domain_suspend_finish(
const psci_power_state_t *target_state)
{
unsigned int cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]);
/* Clear the APU power control register for this cpu */
pm_client_wakeup(proc);
/* enable coherency */
plat_arm_interconnect_enter_coherency();
/* APU was turned off, so restore GIC context */
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
plat_versal_gic_resume();
plat_versal_gic_cpuif_enable();
} else {
plat_versal_gic_cpuif_enable();
plat_versal_gic_pcpu_init();
}
}
void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
/* Enable the gic cpu interface */
@ -47,9 +114,84 @@ void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
plat_versal_gic_cpuif_enable();
}
/**
* versal_pwr_domain_off() - This function performs actions to turn off core
*
* @target_state Targated state
*/
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
{
unsigned int cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]);
/* Prevent interrupts from spuriously waking up this cpu */
plat_versal_gic_cpuif_disable();
/*
* Send request to PMC to power down the appropriate APU CPU
* core.
* According to PSCI specification, CPU_off function does not
* have resume address and CPU core can only be woken up
* invoking CPU_on function, during which resume address will
* be set.
*/
pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0);
}
/**
* versal_validate_power_state() - This function ensures that the power state
* parameter in request is valid.
*
* @power_state Power state of core
* @req_state Requested state
*
* @return Returns status, either success or reason
*/
static int versal_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
int pstate = psci_get_pstate_type(power_state);
assert(req_state);
/* Sanity check the requested state */
if (pstate == PSTATE_TYPE_STANDBY)
req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
else
req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
/* We expect the 'state id' to be zero */
if (psci_get_pstate_id(power_state))
return PSCI_E_INVALID_PARAMS;
return PSCI_E_SUCCESS;
}
/**
* versal_get_sys_suspend_power_state() - Get power state for system suspend
*
* @req_state Requested state
*/
static void versal_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
}
static const struct plat_psci_ops versal_nopmc_psci_ops = {
.pwr_domain_on = versal_pwr_domain_on,
.pwr_domain_off = versal_pwr_domain_off,
.pwr_domain_on_finish = versal_pwr_domain_on_finish,
.pwr_domain_suspend = versal_pwr_domain_suspend,
.pwr_domain_suspend_finish = versal_pwr_domain_suspend_finish,
.validate_power_state = versal_validate_power_state,
.get_sys_suspend_power_state = versal_get_sys_suspend_power_state,
};
/*******************************************************************************

9
plat/xilinx/versal/platform.mk

@ -37,7 +37,8 @@ $(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFOR
VERSAL_CONSOLE ?= pl011
$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE}))
PLAT_INCLUDES := -Iplat/xilinx/common/include/ \
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
-Iplat/xilinx/common/include/ \
-Iplat/xilinx/common/ipi_mailbox_service/ \
-Iplat/xilinx/versal/include/ \
-Iplat/xilinx/versal/pm_service/
@ -47,15 +48,19 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v3/arm_gicv3_common.c \
drivers/arm/gic/v3/gic500.c \
drivers/arm/gic/v3/gicv3_main.c \
drivers/arm/gic/v3/gicv3_helpers.c \
drivers/arm/pl011/aarch64/pl011_console.S \
plat/common/aarch64/crash_console_helpers.S \
plat/arm/common/arm_cci.c \
plat/common/plat_gicv3.c \
plat/xilinx/versal/aarch64/versal_helpers.S \
plat/xilinx/versal/aarch64/versal_common.c
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
BL31_SOURCES += drivers/arm/cci/cci.c \
lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a72.S \
plat/common/plat_psci_common.c \
plat/xilinx/common/ipi.c \

7
plat/xilinx/versal/pm_service/pm_defs.h

@ -15,6 +15,13 @@
* Macro definitions
********************************************************************/
/* State arguments of the self suspend */
#define PM_STATE_CPU_IDLE 0x0U
#define PM_STATE_SUSPEND_TO_RAM 0xFU
#define MAX_LATENCY (~0U)
#define MAX_QOS 100U
/* Processor core device IDs */
#define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_CORE, \
XPM_NODETYPE_DEV_CORE_APU, (IDX))

Loading…
Cancel
Save