xilinx: Add support to send PM API to PMC using IPI for versal

Port ZynqMP PM services for versal to send PM APIs to PMC
using IPI.

Signed-off-by: Tejas Patel <tejas.patel@xilinx.com>
Signed-off-by: Wendy Liang <wendy.liang@xilinx.com>
Signed-off-by: Jolly Shah <jolly.shah@xilinx.com>
Change-Id: I27a52faf27f1a2919213498276a6885a177cb6da
This commit is contained in:
Tejas Patel 2018-12-14 00:55:37 -08:00 committed by Jolly Shah
parent ab36d09709
commit c73a90e571
13 changed files with 554 additions and 3 deletions

View File

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <plat_ipi.h>
#include <versal_def.h>
#include <plat_private.h>
#include <common/debug.h>
@ -38,6 +39,9 @@ void versal_config_setup(void)
{
uint32_t val;
/* Configure IPI data for versal */
versal_ipi_config_table_init();
versal_print_platform_name();
mmio_write_32(VERSAL_CRL_IOU_SWITCH_CTRL,

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Versal IPI management enums and defines */
#ifndef PLAT_IPI_H
#define PLAT_IPI_H
#include <ipi.h>
#include <stdint.h>
/*********************************************************************
* IPI agent IDs macros
********************************************************************/
#define IPI_ID_PMC 1U
#define IPI_ID_APU 2U
#define IPI_ID_RPU0 3U
#define IPI_ID_RPU1 4U
#define IPI_ID_3 5U
#define IPI_ID_4 6U
#define IPI_ID_5 7U
/*********************************************************************
* IPI message buffers
********************************************************************/
#define IPI_BUFFER_BASEADDR 0xFF3F0000U
#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U)
#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200U)
#define IPI_BUFFER_TARGET_APU_OFFSET 0x0U
#define IPI_BUFFER_TARGET_PMC_OFFSET 0x40U
#define IPI_BUFFER_LOCAL_BASE IPI_BUFFER_APU_BASE
#define IPI_BUFFER_REMOTE_BASE IPI_BUFFER_PMC_BASE
#define IPI_BUFFER_TARGET_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET
#define IPI_BUFFER_TARGET_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET
#define IPI_BUFFER_MAX_WORDS 8
#define IPI_BUFFER_REQ_OFFSET 0x0U
#define IPI_BUFFER_RESP_OFFSET 0x20U
/*********************************************************************
* Platform specific IPI API declarations
********************************************************************/
/* Configure IPI table for versal */
void versal_ipi_config_table_init(void);
#endif /* PLAT_IPI_H */

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Contains platform specific definitions of commonly used macros data types
* for PU Power Management. This file should be common for all PU's.
*/
#ifndef PLAT_PM_COMMON_H
#define PLAT_PM_COMMON_H
#include <common/debug.h>
#include <stdint.h>
#include "pm_defs.h"
#define PAYLOAD_ARG_CNT 6U
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
#endif /* PLAT_PM_COMMON_H */

View File

@ -106,4 +106,19 @@
#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8
/* IPI registers and bitfields */
#define IPI0_REG_BASE 0xFF330000
#define IPI0_TRIG_BIT (1 << 2)
#define PMC_IPI_TRIG_BIT (1 << 1)
#define IPI1_REG_BASE 0xFF340000
#define IPI1_TRIG_BIT (1 << 3)
#define IPI2_REG_BASE 0xFF350000
#define IPI2_TRIG_BIT (1 << 4)
#define IPI3_REG_BASE 0xFF360000
#define IPI3_TRIG_BIT (1 << 5)
#define IPI4_REG_BASE 0xFF370000
#define IPI4_TRIG_BIT (1 << 5)
#define IPI5_REG_BASE 0xFF380000
#define IPI5_TRIG_BIT (1 << 6)
#endif /* VERSAL_DEF_H */

View File

@ -37,7 +37,9 @@ $(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/versal/include/
PLAT_INCLUDES := -Iplat/xilinx/common/include/ \
-Iplat/xilinx/versal/include/ \
-Iplat/xilinx/versal/pm_service/
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
lib/xlat_tables/aarch64/xlat_tables.c \
@ -55,9 +57,14 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a72.S \
plat/common/plat_psci_common.c \
plat/xilinx/common/ipi.c \
plat/xilinx/common/pm_service/pm_ipi.c \
plat/xilinx/versal/bl31_versal_setup.c \
plat/xilinx/versal/plat_psci.c \
plat/xilinx/versal/plat_versal.c \
plat/xilinx/versal/plat_topology.c \
plat/xilinx/versal/sip_svc_setup.c \
plat/xilinx/versal/versal_gicv3.c
plat/xilinx/versal/versal_gicv3.c \
plat/xilinx/versal/versal_ipi.c \
plat/xilinx/versal/pm_service/pm_svc_main.c \
plat/xilinx/versal/pm_service/pm_client.c

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* APU specific definition of processors in the subsystem as well as functions
* for getting information about and changing state of the APU.
*/
#include <plat_ipi.h>
#include <platform_def.h>
#include <versal_def.h>
#include <lib/bakery_lock.h>
#include "pm_client.h"
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
static const struct pm_ipi apu_ipi = {
.local_ipi_id = IPI_ID_APU,
.remote_ipi_id = IPI_ID_PMC,
.buffer_base = IPI_BUFFER_APU_BASE,
};
/* Order in pm_procs_all array must match cpu ids */
static const struct pm_proc pm_procs_all[] = {
{
.node_id = XPM_DEVID_ACPU_0,
.ipi = &apu_ipi,
},
{
.node_id = XPM_DEVID_ACPU_1,
.ipi = &apu_ipi,
}
};
const struct pm_proc *primary_proc = &pm_procs_all[0];

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Contains APU specific macros and macros to be defined depending on
* the execution environment.
*/
#ifndef PM_CLIENT_H
#define PM_CLIENT_H
#include "pm_common.h"
#include "pm_defs.h"
/* Global variables to be set in pm_client.c */
extern const struct pm_proc *primary_proc;
#endif /* PM_CLIENT_H */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Versal power management enums and defines */
#ifndef PM_DEFS_H
#define PM_DEFS_H
#include "pm_node.h"
/*********************************************************************
* Macro definitions
********************************************************************/
/* Processor core device IDs */
#define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_CORE, \
XPM_NODETYPE_DEV_CORE_APU, (IDX))
#define XPM_DEVID_ACPU_0 APU_DEVID(XPM_NODEIDX_DEV_ACPU_0)
#define XPM_DEVID_ACPU_1 APU_DEVID(XPM_NODEIDX_DEV_ACPU_1)
/*********************************************************************
* Enum definitions
********************************************************************/
/**
* @PM_RET_SUCCESS: success
* @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated)
* @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated)
* @PM_RET_ERROR_INTERNAL: internal error
* @PM_RET_ERROR_CONFLICT: conflict
* @PM_RET_ERROR_ACCESS: access rights violation
* @PM_RET_ERROR_INVALID_NODE: invalid node
* @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node
* @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted
* @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU
* @PM_RET_ERROR_NODE_USED: node is already in use
*/
enum pm_ret_status {
PM_RET_SUCCESS,
PM_RET_ERROR_ARGS = 1,
PM_RET_ERROR_NOTSUPPORTED = 4,
PM_RET_ERROR_INTERNAL = 2000,
PM_RET_ERROR_CONFLICT = 2001,
PM_RET_ERROR_ACCESS = 2002,
PM_RET_ERROR_INVALID_NODE = 2003,
PM_RET_ERROR_DOUBLE_REQ = 2004,
PM_RET_ERROR_ABORT_SUSPEND = 2005,
PM_RET_ERROR_TIMEOUT = 2006,
PM_RET_ERROR_NODE_USED = 2007
};
#endif /* PM_DEFS_H */

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Versal PM nodes enums and defines */
#ifndef PM_NODE_H
#define PM_NODE_H
/*********************************************************************
* Macro definitions
********************************************************************/
#define NODE_CLASS_SHIFT 26U
#define NODE_SUBCLASS_SHIFT 20U
#define NODE_TYPE_SHIFT 14U
#define NODE_INDEX_SHIFT 0U
#define NODE_CLASS_MASK_BITS 0x3F
#define NODE_SUBCLASS_MASK_BITS 0x3F
#define NODE_TYPE_MASK_BITS 0x3F
#define NODE_INDEX_MASK_BITS 0x3FFF
#define NODE_CLASS_MASK (NODE_CLASS_MASK_BITS << NODE_CLASS_SHIFT)
#define NODE_SUBCLASS_MASK (NODE_SUBCLASS_MASK_BITS << NODE_SUBCLASS_SHIFT)
#define NODE_TYPE_MASK (NODE_TYPE_MASK_BITS << NODE_TYPE_SHIFT)
#define NODE_INDEX_MASK (NODE_INDEX_MASK_BITS << NODE_INDEX_SHIFT)
#define NODEID(CLASS, SUBCLASS, TYPE, INDEX) \
((((CLASS) & NODE_CLASS_MASK_BITS) << NODE_CLASS_SHIFT) | \
(((SUBCLASS) & NODE_SUBCLASS_MASK_BITS) << NODE_SUBCLASS_SHIFT) | \
(((TYPE) & NODE_TYPE_MASK_BITS) << NODE_TYPE_SHIFT) | \
(((INDEX) & NODE_INDEX_MASK_BITS) << NODE_INDEX_SHIFT))
#define NODECLASS(ID) (((ID) & NODE_CLASS_MASK) >> NODE_CLASS_SHIFT)
#define NODESUBCLASS(ID) (((ID) & NODE_SUBCLASS_MASK) >> \
NODE_SUBCLASS_SHIFT)
#define NODETYPE(ID) (((ID) & NODE_TYPE_MASK) >> NODE_TYPE_SHIFT)
#define NODEINDEX(ID) (((ID) & NODE_INDEX_MASK) >> NODE_INDEX_SHIFT)
/*********************************************************************
* Enum definitions
********************************************************************/
/* Node class types */
enum pm_node_class {
XPM_NODECLASS_MIN,
XPM_NODECLASS_POWER,
XPM_NODECLASS_CLOCK,
XPM_NODECLASS_RESET,
XPM_NODECLASS_MEMIC,
XPM_NODECLASS_STMIC,
XPM_NODECLASS_DEVICE,
XPM_NODECLASS_MAX
};
enum pm_device_node_subclass {
/* Device types */
XPM_NODESUBCL_DEV_CORE = 1,
XPM_NODESUBCL_DEV_PERIPH,
XPM_NODESUBCL_DEV_MEM,
XPM_NODESUBCL_DEV_SOC,
XPM_NODESUBCL_DEV_MEM_CTRLR,
XPM_NODESUBCL_DEV_PHY,
};
enum pm_device_node_type {
/* Device types */
XPM_NODETYPE_DEV_CORE_PMC = 1,
XPM_NODETYPE_DEV_CORE_PSM,
XPM_NODETYPE_DEV_CORE_APU,
XPM_NODETYPE_DEV_CORE_RPU,
XPM_NODETYPE_DEV_OCM,
XPM_NODETYPE_DEV_TCM,
XPM_NODETYPE_DEV_L2CACHE,
XPM_NODETYPE_DEV_DDR,
XPM_NODETYPE_DEV_PERIPH,
XPM_NODETYPE_DEV_SOC,
XPM_NODETYPE_DEV_GT,
};
/* Device node Indexes */
enum pm_device_node_idx {
/* Device nodes */
XPM_NODEIDX_DEV_MIN,
/* Processor devices */
XPM_NODEIDX_DEV_PMC_PROC,
XPM_NODEIDX_DEV_PSM_PROC,
XPM_NODEIDX_DEV_ACPU_0,
XPM_NODEIDX_DEV_ACPU_1,
XPM_NODEIDX_DEV_RPU0_0,
XPM_NODEIDX_DEV_RPU0_1,
/* Memory devices */
XPM_NODEIDX_DEV_OCM_0,
XPM_NODEIDX_DEV_OCM_1,
XPM_NODEIDX_DEV_OCM_2,
XPM_NODEIDX_DEV_OCM_3,
XPM_NODEIDX_DEV_TCM_0_A,
XPM_NODEIDX_DEV_TCM_0_B,
XPM_NODEIDX_DEV_TCM_1_A,
XPM_NODEIDX_DEV_TCM_1_B,
XPM_NODEIDX_DEV_L2_BANK_0,
XPM_NODEIDX_DEV_DDR_0,
XPM_NODEIDX_DEV_DDR_1,
XPM_NODEIDX_DEV_DDR_2,
XPM_NODEIDX_DEV_DDR_3,
XPM_NODEIDX_DEV_DDR_4,
XPM_NODEIDX_DEV_DDR_5,
XPM_NODEIDX_DEV_DDR_6,
XPM_NODEIDX_DEV_DDR_7,
/* LPD Peripheral devices */
XPM_NODEIDX_DEV_USB_0,
XPM_NODEIDX_DEV_GEM_0,
XPM_NODEIDX_DEV_GEM_1,
XPM_NODEIDX_DEV_SPI_0,
XPM_NODEIDX_DEV_SPI_1,
XPM_NODEIDX_DEV_I2C_0,
XPM_NODEIDX_DEV_I2C_1,
XPM_NODEIDX_DEV_CAN_FD_0,
XPM_NODEIDX_DEV_CAN_FD_1,
XPM_NODEIDX_DEV_UART_0,
XPM_NODEIDX_DEV_UART_1,
XPM_NODEIDX_DEV_GPIO,
XPM_NODEIDX_DEV_TTC_0,
XPM_NODEIDX_DEV_TTC_1,
XPM_NODEIDX_DEV_TTC_2,
XPM_NODEIDX_DEV_TTC_3,
XPM_NODEIDX_DEV_SWDT_LPD,
/* FPD Peripheral devices */
XPM_NODEIDX_DEV_SWDT_FPD,
/* PMC Peripheral devices */
XPM_NODEIDX_DEV_OSPI,
XPM_NODEIDX_DEV_QSPI,
XPM_NODEIDX_DEV_GPIO_PMC,
XPM_NODEIDX_DEV_I2C_PMC,
XPM_NODEIDX_DEV_SDIO_0,
XPM_NODEIDX_DEV_SDIO_1,
XPM_NODEIDX_DEV_PL_0,
XPM_NODEIDX_DEV_PL_1,
XPM_NODEIDX_DEV_PL_2,
XPM_NODEIDX_DEV_PL_3,
XPM_NODEIDX_DEV_RTC,
XPM_NODEIDX_DEV_ADMA_0,
XPM_NODEIDX_DEV_ADMA_1,
XPM_NODEIDX_DEV_ADMA_2,
XPM_NODEIDX_DEV_ADMA_3,
XPM_NODEIDX_DEV_ADMA_4,
XPM_NODEIDX_DEV_ADMA_5,
XPM_NODEIDX_DEV_ADMA_6,
XPM_NODEIDX_DEV_ADMA_7,
XPM_NODEIDX_DEV_IPI_0,
XPM_NODEIDX_DEV_IPI_1,
XPM_NODEIDX_DEV_IPI_2,
XPM_NODEIDX_DEV_IPI_3,
XPM_NODEIDX_DEV_IPI_4,
XPM_NODEIDX_DEV_IPI_5,
XPM_NODEIDX_DEV_IPI_6,
/* Entire SoC */
XPM_NODEIDX_DEV_SOC,
/* DDR memory controllers */
XPM_NODEIDX_DEV_DDRMC_0,
XPM_NODEIDX_DEV_DDRMC_1,
XPM_NODEIDX_DEV_DDRMC_2,
XPM_NODEIDX_DEV_DDRMC_3,
/* GT devices */
XPM_NODEIDX_DEV_GT_0,
XPM_NODEIDX_DEV_GT_1,
XPM_NODEIDX_DEV_GT_2,
XPM_NODEIDX_DEV_GT_3,
XPM_NODEIDX_DEV_GT_4,
XPM_NODEIDX_DEV_GT_5,
XPM_NODEIDX_DEV_GT_6,
XPM_NODEIDX_DEV_GT_7,
XPM_NODEIDX_DEV_GT_8,
XPM_NODEIDX_DEV_GT_9,
XPM_NODEIDX_DEV_GT_10,
XPM_NODEIDX_DEV_MAX
};
#endif /* PM_NODE_H */

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Top-level SMC handler for Versal power management calls and
* IPI setup functions for communication with PMC.
*/
#include <errno.h>
#include <plat_private.h>
#include "pm_client.h"
#include "pm_ipi.h"
/**
* pm_setup() - PM service setup
*
* @return On success, the initialization function must return 0.
* Any other return value will cause the framework to ignore
* the service
*
* Initialization functions for Versal power management for
* communicaton with PMC.
*
* Called from sip_svc_setup initialization function with the
* rt_svc_init signature.
*/
int pm_setup(void)
{
int status, ret = 0;
status = pm_ipi_init(primary_proc);
if (status < 0) {
INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
ret = status;
}
return ret;
}

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PM_SVC_MAIN_H
#define PM_SVC_MAIN_H
#include <pm_common.h>
int pm_setup(void);
#endif /* PM_SVC_MAIN_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -9,6 +9,7 @@
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <tools_share/uuid.h>
#include "pm_svc_main.h"
/* SMC function IDs for SiP Service queries */
#define VERSAL_SIP_SVC_CALL_COUNT 0x8200ff00
@ -36,6 +37,9 @@ DEFINE_SVC_UUID2(versal_sip_uuid,
*/
static int32_t sip_svc_setup(void)
{
/* PM implementation as SiP Service */
pm_setup();
return 0;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Versal IPI agent registers access management
*/
#include <errno.h>
#include <ipi.h>
#include <plat_ipi.h>
#include <plat_private.h>
#include <string.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/bakery_lock.h>
#include <lib/mmio.h>
/* versal ipi configuration table */
const static struct ipi_config versal_ipi_table[] = {
/* A72 IPI */
[IPI_ID_APU] = {
.ipi_bit_mask = IPI0_TRIG_BIT,
.ipi_reg_base = IPI0_REG_BASE,
.secure_only = 0,
},
/* PMC IPI */
[IPI_ID_PMC] = {
.ipi_bit_mask = PMC_IPI_TRIG_BIT,
.ipi_reg_base = IPI0_REG_BASE,
.secure_only = 0,
},
/* RPU0 IPI */
[IPI_ID_RPU0] = {
.ipi_bit_mask = IPI1_TRIG_BIT,
.ipi_reg_base = IPI1_REG_BASE,
.secure_only = 0,
},
/* RPU1 IPI */
[IPI_ID_RPU1] = {
.ipi_bit_mask = IPI2_TRIG_BIT,
.ipi_reg_base = IPI2_REG_BASE,
.secure_only = 0,
},
/* IPI3 IPI */
[IPI_ID_3] = {
.ipi_bit_mask = IPI3_TRIG_BIT,
.ipi_reg_base = IPI3_REG_BASE,
.secure_only = 0,
},
/* IPI4 IPI */
[IPI_ID_4] = {
.ipi_bit_mask = IPI4_TRIG_BIT,
.ipi_reg_base = IPI4_REG_BASE,
.secure_only = 0,
},
/* IPI5 IPI */
[IPI_ID_5] = {
.ipi_bit_mask = IPI5_TRIG_BIT,
.ipi_reg_base = IPI5_REG_BASE,
.secure_only = 0,
},
};
/* versal_ipi_config_table_init() - Initialize versal IPI configuration data
*
* @ipi_config_table - IPI configuration table
* @ipi_total - Total number of IPI available
*
*/
void versal_ipi_config_table_init(void)
{
ipi_config_table_init(versal_ipi_table, ARRAY_SIZE(versal_ipi_table));
}