Commit 5a8ffeab authored by Tejas Patel's avatar Tejas Patel Committed by Jolly Shah
Browse files

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: default avatarTejas Patel <tejas.patel@xilinx.com>
Signed-off-by: default avatarRajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: default avatarJolly Shah <jolly.shah@xilinx.com>
Change-Id: Ife908a45f32e2037c9c19e13211a8e4b373b8342
parent 394a65aa
...@@ -22,6 +22,8 @@ const mmap_region_t plat_versal_mmap[] = { ...@@ -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(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(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(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 } { 0 }
}; };
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <plat_arm.h>
#include <plat_private.h> #include <plat_private.h>
#include <bl31/bl31.h> #include <bl31/bl31.h>
#include <common/bl_common.h> #include <common/bl_common.h>
...@@ -102,6 +103,9 @@ void bl31_plat_runtime_setup(void) ...@@ -102,6 +103,9 @@ void bl31_plat_runtime_setup(void)
*/ */
void bl31_plat_arch_setup(void) void bl31_plat_arch_setup(void)
{ {
plat_arm_interconnect_init();
plat_arm_interconnect_enter_coherency();
const mmap_region_t bl_regions[] = { const mmap_region_t bl_regions[] = {
MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE, MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
MT_MEMORY | MT_RW | MT_SECURE), MT_MEMORY | MT_RW | MT_SECURE),
......
...@@ -18,6 +18,8 @@ void plat_versal_gic_init(void); ...@@ -18,6 +18,8 @@ void plat_versal_gic_init(void);
void plat_versal_gic_cpuif_enable(void); void plat_versal_gic_cpuif_enable(void);
void plat_versal_gic_cpuif_disable(void); void plat_versal_gic_cpuif_disable(void);
void plat_versal_gic_pcpu_init(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); unsigned int versal_calc_core_pos(u_register_t mpidr);
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
******************************************************************************/ ******************************************************************************/
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) #define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
#define PLAT_VIRT_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 MAX_XLAT_TABLES 5
#define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_SHIFT 6
......
...@@ -55,6 +55,13 @@ ...@@ -55,6 +55,13 @@
******************************************************************************/ ******************************************************************************/
#define VERSAL_IRQ_SEC_PHY_TIMER 29 #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 * UART related constants
******************************************************************************/ ******************************************************************************/
...@@ -97,6 +104,9 @@ ...@@ -97,6 +104,9 @@
#define CRF_RST_APU_ACPU_RESET (1 << 0) #define CRF_RST_APU_ACPU_RESET (1 << 0)
#define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10) #define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10)
#define FPD_MAINCCI_BASE 0xFD000000
#define FPD_MAINCCI_SIZE 0x00100000
/* APU registers and bitfields */ /* APU registers and bitfields */
#define FPD_APU_BASE 0xFD5C0000 #define FPD_APU_BASE 0xFD5C0000
#define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20) #define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20)
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
#include <assert.h>
#include <plat_arm.h>
#include <plat_private.h> #include <plat_private.h>
#include <pm_common.h> #include <pm_common.h>
#include <common/debug.h> #include <common/debug.h>
...@@ -38,6 +40,71 @@ static int versal_pwr_domain_on(u_register_t mpidr) ...@@ -38,6 +40,71 @@ static int versal_pwr_domain_on(u_register_t mpidr)
return PSCI_E_SUCCESS; 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) void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
{ {
/* Enable the gic cpu interface */ /* Enable the gic cpu interface */
...@@ -47,9 +114,84 @@ void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) ...@@ -47,9 +114,84 @@ void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
plat_versal_gic_cpuif_enable(); 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 = { static const struct plat_psci_ops versal_nopmc_psci_ops = {
.pwr_domain_on = versal_pwr_domain_on, .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_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,
}; };
/******************************************************************************* /*******************************************************************************
......
...@@ -37,7 +37,8 @@ $(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFOR ...@@ -37,7 +37,8 @@ $(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFOR
VERSAL_CONSOLE ?= pl011 VERSAL_CONSOLE ?= pl011
$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE})) $(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/common/ipi_mailbox_service/ \
-Iplat/xilinx/versal/include/ \ -Iplat/xilinx/versal/include/ \
-Iplat/xilinx/versal/pm_service/ -Iplat/xilinx/versal/pm_service/
...@@ -47,15 +48,19 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ ...@@ -47,15 +48,19 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
drivers/delay_timer/delay_timer.c \ drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \
drivers/arm/gic/common/gic_common.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_main.c \
drivers/arm/gic/v3/gicv3_helpers.c \ drivers/arm/gic/v3/gicv3_helpers.c \
drivers/arm/pl011/aarch64/pl011_console.S \ drivers/arm/pl011/aarch64/pl011_console.S \
plat/common/aarch64/crash_console_helpers.S \ plat/common/aarch64/crash_console_helpers.S \
plat/arm/common/arm_cci.c \
plat/common/plat_gicv3.c \ plat/common/plat_gicv3.c \
plat/xilinx/versal/aarch64/versal_helpers.S \ plat/xilinx/versal/aarch64/versal_helpers.S \
plat/xilinx/versal/aarch64/versal_common.c 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 \ lib/cpus/aarch64/cortex_a72.S \
plat/common/plat_psci_common.c \ plat/common/plat_psci_common.c \
plat/xilinx/common/ipi.c \ plat/xilinx/common/ipi.c \
......
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
* Macro definitions * 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 */ /* Processor core device IDs */
#define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_CORE, \ #define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_CORE, \
XPM_NODETYPE_DEV_CORE_APU, (IDX)) XPM_NODETYPE_DEV_CORE_APU, (IDX))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment