From 256d133a8a489b8731e5f499457468a4b8a13ab4 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Mon, 24 Sep 2018 22:51:49 -0700 Subject: [PATCH 01/37] plat: xilinx: zynqmp: Use GIC framework for warm restart - Flag GICV2_G0_FOR_EL3 needs to be set for group interrupts to be targeted to EL3. - Raise SGI interrupts for individual CPU cores as GIC API uses CPU num as parameter, not CPU mask. - Flag WARMBOOT_ENABLE_DCACHE_EARLY needs to be set to enable CPU interface mask work properly for all CPU cores which is required when generating SGI. - Call plat_ic_end_of_interrupt() from ttc_fiq_handler() to clear GIC interrupt to avoid same interrupt again. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Change-Id: I71d4935b8d4688a3729c62753ca8a1a77cd92ae7 --- plat/xilinx/zynqmp/plat_psci.c | 5 ++--- plat/xilinx/zynqmp/platform.mk | 2 ++ plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 10 ++++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c index a32e08988..f579f795f 100644 --- a/plat/xilinx/zynqmp/plat_psci.c +++ b/plat/xilinx/zynqmp/plat_psci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -100,9 +100,8 @@ static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state) 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_arm_gic_pcpu_init(); gicv2_cpuif_enable(); - gicv2_pcpu_distif_init(); } static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state) diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 1039e2751..33d648860 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -11,6 +11,8 @@ SEPARATE_CODE_AND_RODATA := 1 ZYNQMP_WDT_RESTART := 0 ZYNQMP_IPI_CRC_CHECK := 0 override RESET_TO_BL31 := 1 +override GICV2_G0_FOR_EL3 := 1 +override WARMBOOT_ENABLE_DCACHE_EARLY := 1 # Do not enable SVE ENABLE_SVE_FOR_NS := 0 diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index 5a320f1ba..98dbe7d6e 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -77,8 +77,12 @@ static void trigger_wdt_restart(void) INFO("Active Cores: %d\n", active_cores); - /* trigger SGI to active cores */ - gicv2_raise_sgi(ARM_IRQ_SEC_SGI_7, target_cpu_list); + for (i = PLATFORM_CORE_COUNT - 1; i >= 0; i--) { + if (target_cpu_list & (1 << i)) { + /* trigger SGI to active cores */ + plat_ic_raise_el3_sgi(ARM_IRQ_SEC_SGI_7, i); + } + } } /** @@ -106,6 +110,8 @@ static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle, { INFO("BL31: Got TTC FIQ\n"); + plat_ic_end_of_interrupt(id); + /* Clear TTC interrupt by reading interrupt register */ mmio_read_32(TTC3_INTR_REGISTER_1); From d4821739ef36f8fda5504fa5c57e0c41f0e09c24 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Fri, 14 Dec 2018 00:55:29 -0800 Subject: [PATCH 02/37] plat: xilinx: versal: Move versal_private.h to include directory Move versal_private.h to platform specific include directory. Also, rename it to plat_private.h instead of having platform name. So, it can be used to common source files which needs platform specific data. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I65eefbea7722ffa2760b992491c00eebef5bcef4 --- plat/xilinx/versal/aarch64/versal_common.c | 5 ++--- plat/xilinx/versal/bl31_versal_setup.c | 6 ++---- .../versal/{versal_private.h => include/plat_private.h} | 8 ++++---- plat/xilinx/versal/plat_psci.c | 5 ++--- plat/xilinx/versal/plat_versal.c | 5 ++--- plat/xilinx/versal/versal_gicv3.c | 5 ++--- 6 files changed, 14 insertions(+), 20 deletions(-) rename plat/xilinx/versal/{versal_private.h => include/plat_private.h} (73%) diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c index 587b797d7..598079cba 100644 --- a/plat/xilinx/versal/aarch64/versal_common.c +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -1,17 +1,16 @@ /* - * 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 */ +#include #include #include #include #include #include - #include "../versal_def.h" -#include "../versal_private.h" /* * Table of regions to map using the MMU. diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c index d7e07e036..0deff9006 100644 --- a/plat/xilinx/versal/bl31_versal_setup.c +++ b/plat/xilinx/versal/bl31_versal_setup.c @@ -1,12 +1,12 @@ /* - * 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 */ #include #include - +#include #include #include #include @@ -15,8 +15,6 @@ #include #include -#include "versal_private.h" - static entry_point_info_t bl32_image_ep_info; static entry_point_info_t bl33_image_ep_info; static console_pl011_t versal_runtime_console; diff --git a/plat/xilinx/versal/versal_private.h b/plat/xilinx/versal/include/plat_private.h similarity index 73% rename from plat/xilinx/versal/versal_private.h rename to plat/xilinx/versal/include/plat_private.h index 5d98d080c..cb35be87e 100644 --- a/plat/xilinx/versal/versal_private.h +++ b/plat/xilinx/versal/include/plat_private.h @@ -1,11 +1,11 @@ /* - * 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 */ -#ifndef VERSAL_PRIVATE_H -#define VERSAL_PRIVATE_H +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H #include @@ -21,4 +21,4 @@ void plat_versal_gic_pcpu_init(void); unsigned int versal_calc_core_pos(u_register_t mpidr); -#endif /* VERSAL_PRIVATE_H */ +#endif /* PLAT_PRIVATE_H */ diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c index 4a443697f..de581bd0b 100644 --- a/plat/xilinx/versal/plat_psci.c +++ b/plat/xilinx/versal/plat_psci.c @@ -1,16 +1,15 @@ /* - * 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 */ +#include #include #include #include #include -#include "versal_private.h" - static uintptr_t versal_sec_entry; static int versal_nopmc_pwr_domain_on(u_register_t mpidr) diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c index 642867da2..a080a76a9 100644 --- a/plat/xilinx/versal/plat_versal.c +++ b/plat/xilinx/versal/plat_versal.c @@ -1,13 +1,12 @@ /* - * 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 */ +#include #include -#include "versal_private.h" - int plat_core_pos_by_mpidr(u_register_t mpidr) { if (mpidr & MPIDR_CLUSTER_MASK) diff --git a/plat/xilinx/versal/versal_gicv3.c b/plat/xilinx/versal/versal_gicv3.c index dcf23b425..08e7cf95a 100644 --- a/plat/xilinx/versal/versal_gicv3.c +++ b/plat/xilinx/versal/versal_gicv3.c @@ -1,9 +1,10 @@ /* - * 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 */ +#include #include #include @@ -11,8 +12,6 @@ #include #include -#include "versal_private.h" - /****************************************************************************** * The following functions are defined as weak to allow a platform to override * the way the GICv3 driver is initialised and used. From ab36d0970945986accaecc0cfe74f27edc16d031 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Fri, 14 Dec 2018 00:55:30 -0800 Subject: [PATCH 03/37] plat: xilinx: versal: Move versal_def.h to include directory Move versal_def.h to platform specific include directory. Also, update source file to include header file from updated path of versal_def.h Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I313592a17552843b9cc7048f31bcaaefa40ffd91 --- plat/xilinx/versal/aarch64/versal_common.c | 2 +- plat/xilinx/versal/include/platform_def.h | 5 ++--- plat/xilinx/versal/{ => include}/versal_def.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) rename plat/xilinx/versal/{ => include}/versal_def.h (97%) diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c index 598079cba..0d7eefb43 100644 --- a/plat/xilinx/versal/aarch64/versal_common.c +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -4,13 +4,13 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include #include #include #include -#include "../versal_def.h" /* * Table of regions to map using the MMU. diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h index 0c4b9544f..e61929cc1 100644 --- a/plat/xilinx/versal/include/platform_def.h +++ b/plat/xilinx/versal/include/platform_def.h @@ -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 */ @@ -8,8 +8,7 @@ #define PLATFORM_DEF_H #include - -#include "../versal_def.h" +#include "versal_def.h" /******************************************************************************* * Generic platform constants diff --git a/plat/xilinx/versal/versal_def.h b/plat/xilinx/versal/include/versal_def.h similarity index 97% rename from plat/xilinx/versal/versal_def.h rename to plat/xilinx/versal/include/versal_def.h index 41c65b94d..d4e388597 100644 --- a/plat/xilinx/versal/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -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 */ From c73a90e571e763e3afc1d9cbef09e7d134b25af8 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Fri, 14 Dec 2018 00:55:37 -0800 Subject: [PATCH 04/37] 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 Signed-off-by: Wendy Liang Signed-off-by: Jolly Shah Change-Id: I27a52faf27f1a2919213498276a6885a177cb6da --- plat/xilinx/versal/aarch64/versal_common.c | 4 + plat/xilinx/versal/include/plat_ipi.h | 55 ++++++ plat/xilinx/versal/include/plat_pm_common.h | 22 +++ plat/xilinx/versal/include/versal_def.h | 15 ++ plat/xilinx/versal/platform.mk | 11 +- plat/xilinx/versal/pm_service/pm_client.c | 38 ++++ plat/xilinx/versal/pm_service/pm_client.h | 21 +++ plat/xilinx/versal/pm_service/pm_defs.h | 55 ++++++ plat/xilinx/versal/pm_service/pm_node.h | 192 ++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_svc_main.c | 42 +++++ plat/xilinx/versal/pm_service/pm_svc_main.h | 14 ++ plat/xilinx/versal/sip_svc_setup.c | 6 +- plat/xilinx/versal/versal_ipi.c | 82 +++++++++ 13 files changed, 554 insertions(+), 3 deletions(-) create mode 100644 plat/xilinx/versal/include/plat_ipi.h create mode 100644 plat/xilinx/versal/include/plat_pm_common.h create mode 100644 plat/xilinx/versal/pm_service/pm_client.c create mode 100644 plat/xilinx/versal/pm_service/pm_client.h create mode 100644 plat/xilinx/versal/pm_service/pm_defs.h create mode 100644 plat/xilinx/versal/pm_service/pm_node.h create mode 100644 plat/xilinx/versal/pm_service/pm_svc_main.c create mode 100644 plat/xilinx/versal/pm_service/pm_svc_main.h create mode 100644 plat/xilinx/versal/versal_ipi.c diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c index 0d7eefb43..2c6ff0537 100644 --- a/plat/xilinx/versal/aarch64/versal_common.c +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include @@ -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, diff --git a/plat/xilinx/versal/include/plat_ipi.h b/plat/xilinx/versal/include/plat_ipi.h new file mode 100644 index 000000000..6b08f322d --- /dev/null +++ b/plat/xilinx/versal/include/plat_ipi.h @@ -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 +#include + +/********************************************************************* + * 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 */ diff --git a/plat/xilinx/versal/include/plat_pm_common.h b/plat/xilinx/versal/include/plat_pm_common.h new file mode 100644 index 000000000..6b202c746 --- /dev/null +++ b/plat/xilinx/versal/include/plat_pm_common.h @@ -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 +#include +#include "pm_defs.h" + +#define PAYLOAD_ARG_CNT 6U +#define PAYLOAD_ARG_SIZE 4U /* size in bytes */ + +#endif /* PLAT_PM_COMMON_H */ diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index d4e388597..21883a1a9 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -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 */ diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk index 1c56364c8..190be328b 100644 --- a/plat/xilinx/versal/platform.mk +++ b/plat/xilinx/versal/platform.mk @@ -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 diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c new file mode 100644 index 000000000..6183b7822 --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_client.c @@ -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 +#include +#include +#include +#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]; diff --git a/plat/xilinx/versal/pm_service/pm_client.h b/plat/xilinx/versal/pm_service/pm_client.h new file mode 100644 index 000000000..6840bb1dd --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_client.h @@ -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 */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h new file mode 100644 index 000000000..c435b7ada --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -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 */ diff --git a/plat/xilinx/versal/pm_service/pm_node.h b/plat/xilinx/versal/pm_service/pm_node.h new file mode 100644 index 000000000..1b82ec70d --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_node.h @@ -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 */ diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c new file mode 100644 index 000000000..a1c457fa1 --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -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 +#include +#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; +} diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.h b/plat/xilinx/versal/pm_service/pm_svc_main.h new file mode 100644 index 000000000..ec279b642 --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_svc_main.h @@ -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 + +int pm_setup(void); + +#endif /* PM_SVC_MAIN_H */ diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c index 8f2180b21..6437bbf2c 100644 --- a/plat/xilinx/versal/sip_svc_setup.c +++ b/plat/xilinx/versal/sip_svc_setup.c @@ -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 #include #include +#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; } diff --git a/plat/xilinx/versal/versal_ipi.c b/plat/xilinx/versal/versal_ipi.c new file mode 100644 index 000000000..27541ff4b --- /dev/null +++ b/plat/xilinx/versal/versal_ipi.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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)); +} From 95794c732367ff2bc595f9226d70bb8d6eaaa1d8 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 8 Jan 2019 01:46:35 -0800 Subject: [PATCH 05/37] xilinx: versal: Add get_api_version support Add support for EEMI API get_api_verion. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Ic1ef90a194ae6164994a7fc5d8ff0b7b192636fe --- plat/xilinx/versal/platform.mk | 1 + plat/xilinx/versal/pm_service/pm_api_sys.c | 45 ++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 18 +++++++++ plat/xilinx/versal/pm_service/pm_defs.h | 3 ++ 4 files changed, 67 insertions(+) create mode 100644 plat/xilinx/versal/pm_service/pm_api_sys.c create mode 100644 plat/xilinx/versal/pm_service/pm_api_sys.h diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk index 190be328b..eb1f0bb61 100644 --- a/plat/xilinx/versal/platform.mk +++ b/plat/xilinx/versal/platform.mk @@ -67,4 +67,5 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ 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_api_sys.c \ plat/xilinx/versal/pm_service/pm_client.c diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c new file mode 100644 index 000000000..618624e88 --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Versal system level PM-API functions and communication with PMC via + * IPI interrupts + */ + +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" + +/********************************************************************* + * Target module IDs macros + ********************************************************************/ +#define LIBPM_MODULE_ID 0x2 +#define LOADER_MODULE_ID 0x7 + +/** + * Assigning of argument values into array elements. + */ +#define PM_PACK_PAYLOAD1(pl, mid, arg0) { \ + pl[0] = (uint32_t)((uint32_t)((arg0) & 0xFF) | (mid << 8)); \ +} + +/* PM API functions */ + +/** + * pm_get_api_version() - Get version number of PMC PM firmware + * @version Returns 32-bit version number of PMC Power Management Firmware + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_api_version(unsigned int *version) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_API_VERSION); + return pm_ipi_send_sync(primary_proc, payload, version, 1); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h new file mode 100644 index 000000000..59f39524d --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_API_SYS_H +#define PM_API_SYS_H + +#include + +/********************************************************** + * PM API function declarations + **********************************************************/ + +enum pm_ret_status pm_get_api_version(unsigned int *version); + +#endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index c435b7ada..ff3d26603 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -22,6 +22,9 @@ #define XPM_DEVID_ACPU_0 APU_DEVID(XPM_NODEIDX_DEV_ACPU_0) #define XPM_DEVID_ACPU_1 APU_DEVID(XPM_NODEIDX_DEV_ACPU_1) +/* PM API ids */ +#define PM_GET_API_VERSION 1U + /********************************************************************* * Enum definitions ********************************************************************/ From fbb32695a27536818004e60772bd4240ae3cec1b Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Sun, 8 Dec 2019 23:29:44 -0800 Subject: [PATCH 06/37] xilinx: versal: Add support for suspend related APIs Add support for below suspend related APIs. - self_suspend - abort_suspend - request_suspend Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: If568e0cd33b64754fe66f66fc0cdd0ec62c1b32e --- plat/xilinx/versal/include/versal_def.h | 2 + plat/xilinx/versal/pm_service/pm_api_sys.c | 115 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 10 ++ plat/xilinx/versal/pm_service/pm_client.c | 57 ++++++++++ plat/xilinx/versal/pm_service/pm_client.h | 4 + plat/xilinx/versal/pm_service/pm_defs.h | 10 ++ 6 files changed, 198 insertions(+) diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index 21883a1a9..a77fa30d0 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -105,6 +105,8 @@ #define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90) #define FPD_APU_CONFIG_0_VINITHI_SHIFT 8 +#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1 +#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2 /* IPI registers and bitfields */ #define IPI0_REG_BASE 0xFF330000 diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 618624e88..16c2541b9 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -11,6 +11,7 @@ #include #include +#include #include "pm_api_sys.h" #include "pm_client.h" @@ -27,6 +28,31 @@ pl[0] = (uint32_t)((uint32_t)((arg0) & 0xFF) | (mid << 8)); \ } +#define PM_PACK_PAYLOAD2(pl, mid, arg0, arg1) { \ + pl[1] = (uint32_t)(arg1); \ + PM_PACK_PAYLOAD1(pl, mid, arg0); \ +} + +#define PM_PACK_PAYLOAD3(pl, mid, arg0, arg1, arg2) { \ + pl[2] = (uint32_t)(arg2); \ + PM_PACK_PAYLOAD2(pl, mid, arg0, arg1); \ +} + +#define PM_PACK_PAYLOAD4(pl, mid, arg0, arg1, arg2, arg3) { \ + pl[3] = (uint32_t)(arg3); \ + PM_PACK_PAYLOAD3(pl, mid, arg0, arg1, arg2); \ +} + +#define PM_PACK_PAYLOAD5(pl, mid, arg0, arg1, arg2, arg3, arg4) { \ + pl[4] = (uint32_t)(arg4); \ + PM_PACK_PAYLOAD4(pl, mid, arg0, arg1, arg2, arg3); \ +} + +#define PM_PACK_PAYLOAD6(pl, mid, arg0, arg1, arg2, arg3, arg4, arg5) { \ + pl[5] = (uint32_t)(arg5); \ + PM_PACK_PAYLOAD5(pl, mid, arg0, arg1, arg2, arg3, arg4); \ +} + /* PM API functions */ /** @@ -43,3 +69,92 @@ enum pm_ret_status pm_get_api_version(unsigned int *version) PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_API_VERSION); return pm_ipi_send_sync(primary_proc, payload, version, 1); } + +/** + * pm_self_suspend() - PM call for processor to suspend itself + * @nid Node id of the processor or subsystem + * @latency Requested maximum wakeup latency (not supported) + * @state Requested state + * @address Resume address + * + * This is a blocking call, it will return only once PMU has responded. + * On a wakeup, resume address will be automatically set by PMU. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_self_suspend(uint32_t nid, + unsigned int latency, + unsigned int state, + uintptr_t address) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + unsigned int cpuid = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpuid); + + if (!proc) { + WARN("Failed to get proc %d\n", cpuid); + return PM_RET_ERROR_INTERNAL; + } + + /* + * Do client specific suspend operations + * (e.g. set powerdown request bit) + */ + pm_client_suspend(proc, state); + + /* Send request to the PLM */ + PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, PM_SELF_SUSPEND, + proc->node_id, latency, state, address, + (address >> 32)); + return pm_ipi_send_sync(proc, payload, NULL, 0); +} + +/** + * 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 pm_ret_status pm_abort_suspend(enum pm_abort_reason reason) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* + * Do client specific abort suspend operations + * (e.g. enable interrupts and clear powerdown request bit) + */ + pm_client_abort_suspend(); + + /* Send request to the PLM */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_ABORT_SUSPEND, reason, + primary_proc->node_id); + return pm_ipi_send(primary_proc, payload); +} + +/** + * 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 pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, + unsigned int latency, unsigned int state) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_REQ_SUSPEND, target, + latency, state); + if (ack == IPI_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 59f39524d..f67682329 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -8,11 +8,21 @@ #define PM_API_SYS_H #include +#include "pm_defs.h" /********************************************************** * PM API function declarations **********************************************************/ enum pm_ret_status pm_get_api_version(unsigned int *version); +enum pm_ret_status pm_self_suspend(uint32_t nid, + unsigned int latency, + unsigned int state, + uintptr_t address); +enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason); +enum pm_ret_status pm_req_suspend(uint32_t target, + uint8_t ack, + unsigned int latency, + unsigned int state); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c index 6183b7822..636b719fd 100644 --- a/plat/xilinx/versal/pm_service/pm_client.c +++ b/plat/xilinx/versal/pm_service/pm_client.c @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include "pm_client.h" DEFINE_BAKERY_LOCK(pm_client_secure_lock); @@ -28,11 +31,65 @@ static const struct pm_proc pm_procs_all[] = { { .node_id = XPM_DEVID_ACPU_0, .ipi = &apu_ipi, + .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, }, { .node_id = XPM_DEVID_ACPU_1, .ipi = &apu_ipi, + .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, } }; const struct pm_proc *primary_proc = &pm_procs_all[0]; + +/** + * pm_client_suspend() - Client-specific suspend actions + * + * This function should contain any PU-specific actions + * required prior to sending suspend request to PMU + * Actions taken depend on the state system is suspending to. + */ +void pm_client_suspend(const struct pm_proc *proc, unsigned int state) +{ + bakery_lock_get(&pm_client_secure_lock); + + /* Set powerdown request */ + mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | + proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_client_abort_suspend() - Client-specific abort-suspend actions + * + * This function should contain any PU-specific actions + * required for aborting a prior suspend request + */ +void pm_client_abort_suspend(void) +{ + /* Enable interrupts at processor level (for current cpu) */ + gicv3_cpuif_enable(plat_my_core_pos()); + + bakery_lock_get(&pm_client_secure_lock); + + /* Clear powerdown request */ + mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & + ~primary_proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_get_proc() - returns pointer to the proc structure + * @cpuid: id of the cpu whose proc struct pointer should be returned + * + * Return: pointer to a proc structure if proc is found, otherwise NULL + */ +const struct pm_proc *pm_get_proc(unsigned int cpuid) +{ + if (cpuid < ARRAY_SIZE(pm_procs_all)) + return &pm_procs_all[cpuid]; + + return NULL; +} diff --git a/plat/xilinx/versal/pm_service/pm_client.h b/plat/xilinx/versal/pm_service/pm_client.h index 6840bb1dd..228094e67 100644 --- a/plat/xilinx/versal/pm_service/pm_client.h +++ b/plat/xilinx/versal/pm_service/pm_client.h @@ -15,6 +15,10 @@ #include "pm_common.h" #include "pm_defs.h" +/* Functions to be implemented by each PU */ +void pm_client_suspend(const struct pm_proc *proc, unsigned int state); +void pm_client_abort_suspend(void); + /* Global variables to be set in pm_client.c */ extern const struct pm_proc *primary_proc; diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index ff3d26603..d482cb75a 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -24,11 +24,21 @@ /* PM API ids */ #define PM_GET_API_VERSION 1U +#define PM_REQ_SUSPEND 6U +#define PM_SELF_SUSPEND 7U +#define PM_ABORT_SUSPEND 9U /********************************************************************* * Enum definitions ********************************************************************/ +enum pm_abort_reason { + ABORT_REASON_WKUP_EVENT = 100, + ABORT_REASON_PU_BUSY, + ABORT_REASON_NO_PWRDN, + ABORT_REASON_UNKNOWN, +}; + /** * @PM_RET_SUCCESS: success * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated) From cf1e56a4e74752f3ee7e2953ebd2ebb4ed8f9e20 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 8 Jan 2019 01:46:37 -0800 Subject: [PATCH 07/37] xilinx: versal: Implement device related PM APIs Implement below device related PM APIs: - Request device - Release device - Set requirement - Get device status Signed-off-by: Tejas Patel Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Jolly Shah Change-Id: I9d84b9ee1be3ee6c5f27a4d6dc324113fc1acb68 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 77 ++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 6 ++ plat/xilinx/versal/pm_service/pm_defs.h | 20 ++++++ 3 files changed, 103 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 16c2541b9..64c1e3503 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -158,3 +158,80 @@ enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, else return pm_ipi_send(primary_proc, payload); } + +/** + * pm_request_device() - Request a device + * @device_id Device ID + * @capabilities Requested capabilities for the device + * @qos Required Quality of Service + * @ack Flag to specify whether acknowledge requested + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, + uint32_t qos, uint32_t ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REQUEST_DEVICE, + device_id, capabilities, qos, ack); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_release_device() - Release a device + * @device_id Device ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_release_device(uint32_t device_id) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_RELEASE_DEVICE, + device_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_set_requirement() - Set requirement for the device + * @device_id Device ID + * @capabilities Requested capabilities for the device + * @latency Requested maximum latency + * @qos Required Quality of Service + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, + uint32_t latency, uint32_t qos) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_SET_REQUIREMENT, + device_id, capabilities, latency, qos); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_get_device_status() - Get device's status + * @device_id Device ID + * @response Buffer to store device status response + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_GET_DEVICE_STATUS, + device_id); + + return pm_ipi_send_sync(primary_proc, payload, response, 3); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index f67682329..6e50e94b9 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -24,5 +24,11 @@ enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, unsigned int latency, unsigned int state); +enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, + uint32_t qos, uint32_t ack); +enum pm_ret_status pm_release_device(uint32_t device_id); +enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, + uint32_t latency, uint32_t qos); +enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index d482cb75a..feaeee120 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -24,9 +24,13 @@ /* PM API ids */ #define PM_GET_API_VERSION 1U +#define PM_GET_DEVICE_STATUS 3U #define PM_REQ_SUSPEND 6U #define PM_SELF_SUSPEND 7U #define PM_ABORT_SUSPEND 9U +#define PM_REQUEST_DEVICE 13U +#define PM_RELEASE_DEVICE 14U +#define PM_SET_REQUIREMENT 15U /********************************************************************* * Enum definitions @@ -39,6 +43,22 @@ enum pm_abort_reason { ABORT_REASON_UNKNOWN, }; +/** + * Subsystem IDs + */ +typedef enum { + XPM_SUBSYSID_PMC, + XPM_SUBSYSID_PSM, + XPM_SUBSYSID_APU, + XPM_SUBSYSID_RPU0_LOCK, + XPM_SUBSYSID_RPU0_0, + XPM_SUBSYSID_RPU0_1, + XPM_SUBSYSID_DDR0, + XPM_SUBSYSID_ME, + XPM_SUBSYSID_PL, + XPM_SUBSYSID_MAX, +} XPm_SubsystemId; + /** * @PM_RET_SUCCESS: success * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated) From 9c3c5e0737c91f5523f93797a2b38b9477f241b7 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 8 Jan 2019 01:46:38 -0800 Subject: [PATCH 08/37] xilinx: versal: Implement reset related PM APIs Implement below reset related APIs: - Reset assert - Get reset status Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Id42c9d3950a0d69125cb0eab79b75e5d22674f14 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 35 ++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 2 ++ 3 files changed, 39 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 64c1e3503..51f1c2d4d 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -235,3 +235,38 @@ enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response) return pm_ipi_send_sync(primary_proc, payload, response, 3); } + +/** + * pm_reset_assert() - Assert/De-assert reset + * @reset Reset ID + * @assert Assert (1) or de-assert (0) + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_RESET_ASSERT, reset, + assert); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_reset_get_status() - Get current status of a reset line + * @reset Reset ID + * @status Returns current status of selected reset ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_RESET_ASSERT, reset); + + return pm_ipi_send_sync(primary_proc, payload, status, 1); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 6e50e94b9..28e5504a7 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -30,5 +30,7 @@ enum pm_ret_status pm_release_device(uint32_t device_id); enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, uint32_t latency, uint32_t qos); enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response); +enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert); +enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index feaeee120..1b8871f7f 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -31,6 +31,8 @@ #define PM_REQUEST_DEVICE 13U #define PM_RELEASE_DEVICE 14U #define PM_SET_REQUIREMENT 15U +#define PM_RESET_ASSERT 17U +#define PM_RESET_GET_STATUS 18U /********************************************************************* * Enum definitions From 0ed83c621c7eb8460806fff48c573f3d293b37ad Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 8 Jan 2019 01:46:39 -0800 Subject: [PATCH 09/37] xilinx: versal: Implement pin control related PM APIs Implement below pin control related APIs: - Request pin - Release pin - Set pin function - Get pin function - Set pin parameter value - Get pin parameter value Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Ib805cc8c936b63206d44bf1f7bebd0f03f7b3c01 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 108 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 8 ++ plat/xilinx/versal/pm_service/pm_defs.h | 6 ++ 3 files changed, 122 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 51f1c2d4d..149f2c8a9 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -270,3 +270,111 @@ enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status) return pm_ipi_send_sync(primary_proc, payload, status, 1); } + +/** + * pm_pinctrl_request() - Request a pin + * @pin Pin ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_request(uint32_t pin) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PINCTRL_REQUEST, pin); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_release() - Release a pin + * @pin Pin ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_release(uint32_t pin) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PINCTRL_RELEASE, pin); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_set_function() - Set pin function + * @pin Pin ID + * @function Function ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PINCTRL_SET_FUNCTION, pin, + function) + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_get_function() - Get function set on the pin + * @pin Pin ID + * @function Function set on the pin + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PINCTRL_SET_FUNCTION, + pin); + + return pm_ipi_send_sync(primary_proc, payload, function, 1); +} + +/** + * pm_pinctrl_set_pin_param() - Set configuration parameter for the pin + * @pin Pin ID + * @param Parameter ID + * @value Parameter value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, + uint32_t value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_PINCTRL_CONFIG_PARAM_SET, + pin, param, value); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_get_pin_param() - Get configuration parameter value for the pin + * @pin Pin ID + * @param Parameter ID + * @value Buffer to store parameter value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PINCTRL_CONFIG_PARAM_GET, + pin, param); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 28e5504a7..c3f26515a 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -32,5 +32,13 @@ enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response); enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert); enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status); +enum pm_ret_status pm_pinctrl_request(uint32_t pin); +enum pm_ret_status pm_pinctrl_release(uint32_t pin); +enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function); +enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function); +enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, + uint32_t value); +enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, + uint32_t *value); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 1b8871f7f..8a42663ed 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -33,6 +33,12 @@ #define PM_SET_REQUIREMENT 15U #define PM_RESET_ASSERT 17U #define PM_RESET_GET_STATUS 18U +#define PM_PINCTRL_REQUEST 28U +#define PM_PINCTRL_RELEASE 29U +#define PM_PINCTRL_GET_FUNCTION 30U +#define PM_PINCTRL_SET_FUNCTION 31U +#define PM_PINCTRL_CONFIG_PARAM_GET 32U +#define PM_PINCTRL_CONFIG_PARAM_SET 33U /********************************************************************* * Enum definitions From 2394b94bfd05292f81fd5ec3d66a2d5ca51ab3a0 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 8 Jan 2019 01:46:40 -0800 Subject: [PATCH 10/37] xilinx: versal: Implement clock related PM APIs Implement below clock related APIs: - Clock enable - Clock disable - Clock get status - Clock set divider - Clock get divider - Clock set parent - Clock get parent Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Ibb3606e88ac6796d9d759226908b2c2997c5fea0 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 119 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 7 ++ plat/xilinx/versal/pm_service/pm_defs.h | 9 ++ 3 files changed, 135 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 149f2c8a9..8ac9a1d0d 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -378,3 +378,122 @@ enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, return pm_ipi_send_sync(primary_proc, payload, value, 1); } + +/** + * pm_clock_enable() - Enable the clock + * @clk_id Clock ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_enable(uint32_t clk_id) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_ENABLE, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_disable() - Disable the clock + * @clk_id Clock ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_disable(uint32_t clk_id) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_DISABLE, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_state() - Get clock status + * @clk_id Clock ID + * @state: Buffer to store clock status (1: Enabled, 0:Disabled) + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETSTATE, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, state, 1); +} + +/** + * pm_clock_set_divider() - Set divider for the clock + * @clk_id Clock ID + * @divider Divider value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_CLOCK_SETDIVIDER, clk_id, + divider); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_divider() - Get divider value for the clock + * @clk_id Clock ID + * @divider: Buffer to store clock divider value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETDIVIDER, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, divider, 1); +} + +/** + * pm_clock_set_parent() - Set parent for the clock + * @clk_id Clock ID + * @parent Parent ID + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_CLOCK_SETPARENT, clk_id, + parent); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_parent() - Get parent value for the clock + * @clk_id Clock ID + * @parent: Buffer to store clock parent value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETPARENT, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, parent, 1); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index c3f26515a..a91895cca 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -40,5 +40,12 @@ enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, uint32_t value); enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, uint32_t *value); +enum pm_ret_status pm_clock_enable(uint32_t clk_id); +enum pm_ret_status pm_clock_disable(uint32_t clk_id); +enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state); +enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider); +enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider); +enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent); +enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 8a42663ed..e9aa51286 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -39,6 +39,15 @@ #define PM_PINCTRL_SET_FUNCTION 31U #define PM_PINCTRL_CONFIG_PARAM_GET 32U #define PM_PINCTRL_CONFIG_PARAM_SET 33U +#define PM_CLOCK_ENABLE 36U +#define PM_CLOCK_DISABLE 37U +#define PM_CLOCK_GETSTATE 38U +#define PM_CLOCK_SETDIVIDER 39U +#define PM_CLOCK_GETDIVIDER 40U +#define PM_CLOCK_SETRATE 41U +#define PM_CLOCK_GETRATE 42U +#define PM_CLOCK_SETPARENT 43U +#define PM_CLOCK_GETPARENT 44U /********************************************************************* * Enum definitions From baccc60e8b79fef7e34f067facebcb166119f69b Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 8 Jan 2019 01:46:41 -0800 Subject: [PATCH 11/37] xilinx: versal: Implement PLL related PM APIs Implement below PLL related APIs: - Set PLL parameter - Get PLL parameter - Set PLL mode - Get PLL mode Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I37749d05cdb73641d32da120d319cf36df97c73f --- plat/xilinx/versal/pm_service/pm_api_sys.c | 75 ++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 6 ++ plat/xilinx/versal/pm_service/pm_defs.h | 4 ++ 3 files changed, 85 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 8ac9a1d0d..1b32e4bd9 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -497,3 +497,78 @@ enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent) return pm_ipi_send_sync(primary_proc, payload, parent, 1); } + +/** + * pm_pll_set_param() - Set PLL parameter + * @clk_id PLL clock ID + * @param PLL parameter ID + * @value Value to set for PLL parameter + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, + uint32_t value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_PLL_SET_PARAMETER, clk_id, + param, value); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pll_get_param() - Get PLL parameter value + * @clk_id PLL clock ID + * @param PLL parameter ID + * @value: Buffer to store PLL parameter value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PLL_GET_PARAMETER, clk_id, + param); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_pll_set_mode() - Set PLL mode + * @clk_id PLL clock ID + * @mode PLL mode + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PLL_SET_MODE, clk_id, + mode); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pll_get_mode() - Get PLL mode + * @clk_id PLL clock ID + * @mode: Buffer to store PLL mode + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PLL_GET_MODE, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, mode, 1); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index a91895cca..025255bda 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -47,5 +47,11 @@ enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider); enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider); enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent); enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent); +enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, + uint32_t value); +enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, + uint32_t *value); +enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode); +enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index e9aa51286..ce2605a14 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -48,6 +48,10 @@ #define PM_CLOCK_GETRATE 42U #define PM_CLOCK_SETPARENT 43U #define PM_CLOCK_GETPARENT 44U +#define PM_PLL_SET_PARAMETER 48U +#define PM_PLL_GET_PARAMETER 49U +#define PM_PLL_SET_MODE 50U +#define PM_PLL_GET_MODE 51U /********************************************************************* * Enum definitions From ab43d15b9137cf8def6d97ee878d60cad48ae770 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 9 Jan 2019 04:10:29 -0800 Subject: [PATCH 12/37] xilinx: versal: Add SMC handler for EEMI API Add SMC handler for EEMI API calls coming from EL1/EL2. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: If0ef2a1f2cfc2747be6b91828371bcbec56b1e15 --- plat/xilinx/versal/pm_service/pm_svc_main.c | 203 ++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_svc_main.h | 3 + plat/xilinx/versal/sip_svc_setup.c | 6 + 3 files changed, 212 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index a1c457fa1..5dd315799 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -11,9 +11,15 @@ #include #include +#include +#include +#include "pm_api_sys.h" #include "pm_client.h" #include "pm_ipi.h" +/* pm_up = true - UP, pm_up = false - DOWN */ +static bool pm_up; + /** * pm_setup() - PM service setup * @@ -36,7 +42,204 @@ int pm_setup(void) if (status < 0) { INFO("BL31: PM Service Init Failed, Error Code %d!\n", status); ret = status; + } else { + pm_up = true; } return ret; } + +/** + * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2. + * @smc_fid - Function Identifier + * @x1 - x4 - Arguments + * @cookie - Unused + * @handler - Pointer to caller's context structure + * + * @return - Unused + * + * Determines that smc_fid is valid and supported PM SMC Function ID from the + * list of pm_api_ids, otherwise completes the request with + * the unknown SMC Function ID + * + * The SMC calls for PM service are forwarded from SIP Service SMC handler + * function with rt_svc_handle signature + */ +uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, void *handle, uint64_t flags) +{ + enum pm_ret_status ret; + + uint32_t pm_arg[4]; + + /* Handle case where PM wasn't initialized properly */ + if (!pm_up) + SMC_RET1(handle, SMC_UNK); + + pm_arg[0] = (uint32_t)x1; + pm_arg[1] = (uint32_t)(x1 >> 32); + pm_arg[2] = (uint32_t)x2; + pm_arg[3] = (uint32_t)(x2 >> 32); + + switch (smc_fid & FUNCID_NUM_MASK) { + /* PM API Functions */ + case PM_SELF_SUSPEND: + ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_SUSPEND: + ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_ABORT_SUSPEND: + ret = pm_abort_suspend(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQUEST_DEVICE: + ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_RELEASE_DEVICE: + ret = pm_release_device(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SET_REQUIREMENT: + ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_API_VERSION: + { + uint32_t api_version; + + ret = pm_get_api_version(&api_version); + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)api_version << 32)); + } + + case PM_GET_DEVICE_STATUS: + { + uint32_t buff[3]; + + ret = pm_get_device_status(pm_arg[0], buff); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buff[0] << 32), + (uint64_t)buff[1] | ((uint64_t)buff[2] << 32)); + } + + case PM_RESET_ASSERT: + ret = pm_reset_assert(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_RESET_GET_STATUS: + { + uint32_t reset_status; + + ret = pm_reset_get_status(pm_arg[0], &reset_status); + SMC_RET1(handle, (uint64_t)ret | + ((uint64_t)reset_status << 32)); + } + + case PM_PINCTRL_REQUEST: + ret = pm_pinctrl_request(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_RELEASE: + ret = pm_pinctrl_release(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_GET_FUNCTION: + { + uint32_t value = 0; + + ret = pm_pinctrl_get_function(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_PINCTRL_SET_FUNCTION: + ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_CONFIG_PARAM_GET: + { + uint32_t value; + + ret = pm_pinctrl_get_pin_param(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_PINCTRL_CONFIG_PARAM_SET: + ret = pm_pinctrl_set_pin_param(pm_arg[0], pm_arg[1], pm_arg[2]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_ENABLE: + ret = pm_clock_enable(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_DISABLE: + ret = pm_clock_disable(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETSTATE: + { + uint32_t value; + + ret = pm_clock_get_state(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_CLOCK_SETDIVIDER: + ret = pm_clock_set_divider(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETDIVIDER: + { + uint32_t value; + + ret = pm_clock_get_divider(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_CLOCK_SETPARENT: + ret = pm_clock_set_parent(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETPARENT: + { + uint32_t value; + + ret = pm_clock_get_parent(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_PLL_SET_PARAMETER: + ret = pm_pll_set_param(pm_arg[0], pm_arg[1], pm_arg[2]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_PARAMETER: + { + uint32_t value; + + ret = pm_pll_get_param(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32)); + } + + case PM_PLL_SET_MODE: + ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_MODE: + { + uint32_t mode; + + ret = pm_pll_get_mode(pm_arg[0], &mode); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32)); + } + + default: + WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.h b/plat/xilinx/versal/pm_service/pm_svc_main.h index ec279b642..71329ca93 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.h +++ b/plat/xilinx/versal/pm_service/pm_svc_main.h @@ -10,5 +10,8 @@ #include int pm_setup(void); +uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, void *handle, + uint64_t flags); #endif /* PM_SVC_MAIN_H */ diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c index 6437bbf2c..404c496a7 100644 --- a/plat/xilinx/versal/sip_svc_setup.c +++ b/plat/xilinx/versal/sip_svc_setup.c @@ -58,6 +58,12 @@ uintptr_t sip_svc_smc_handler(uint32_t smc_fid, void *handle, u_register_t flags) { + /* Let PM SMC handler deal with PM-related requests */ + if (is_pm_fid(smc_fid)) { + return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + /* Let PM SMC handler deal with PM-related requests */ switch (smc_fid) { case VERSAL_SIP_SVC_CALL_COUNT: From ffecfe79fb4a1ae6c5d637bccfa4ddb3dd2b59d5 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Thu, 10 Jan 2019 03:03:47 -0800 Subject: [PATCH 13/37] xilinx: versal: Implement power down/restart related EEMI API Add power down/restart related below API - Force power down - System shutdown Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Icd4a922923b1fd50eca1f5361f1e604aedcdb529 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 40 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 2 ++ plat/xilinx/versal/pm_service/pm_svc_main.c | 8 +++++ 4 files changed, 52 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 1b32e4bd9..be28a41ae 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -572,3 +572,43 @@ enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode) return pm_ipi_send_sync(primary_proc, payload, mode, 1); } + +/** + * pm_force_powerdown() - PM call to request for another PU or subsystem to + * be powered down forcefully + * @target Device ID of the PU node to be forced powered down. + * @ack Flag to specify whether acknowledge is requested + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_FORCE_POWERDOWN, target, + ack); + + if (ack == IPI_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_system_shutdown() - PM call to request a system shutdown or restart + * @type Shutdown or restart? 0=shutdown, 1=restart + * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SYSTEM_SHUTDOWN, type, + subtype); + + return pm_ipi_send_non_blocking(primary_proc, payload); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 025255bda..375199549 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -53,5 +53,7 @@ enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, uint32_t *value); enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode); enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode); +enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack); +enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index ce2605a14..248c7151f 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -27,7 +27,9 @@ #define PM_GET_DEVICE_STATUS 3U #define PM_REQ_SUSPEND 6U #define PM_SELF_SUSPEND 7U +#define PM_FORCE_POWERDOWN 8U #define PM_ABORT_SUSPEND 9U +#define PM_SYSTEM_SHUTDOWN 12U #define PM_REQUEST_DEVICE 13U #define PM_RELEASE_DEVICE 14U #define PM_SET_REQUIREMENT 15U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 5dd315799..aa008ac9b 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -88,6 +88,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, pm_arg[3]); SMC_RET1(handle, (uint64_t)ret); + case PM_FORCE_POWERDOWN: + ret = pm_force_powerdown(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + case PM_REQ_SUSPEND: ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); @@ -97,6 +101,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_abort_suspend(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); + case PM_SYSTEM_SHUTDOWN: + ret = pm_system_shutdown(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + case PM_REQUEST_DEVICE: ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); From d62fa4bcb1e2e82a34053b66a9ec367c2f6c85de Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Thu, 10 Jan 2019 03:03:48 -0800 Subject: [PATCH 14/37] plat: xilinx: versal: Implement PM IOCTL API Add PM IOCTL EEMI. Below PLL related IOCTLs are not available in versal PLM. * IOCTL_SET_PLL_FRAC_MODE * IOCTL_GET_PLL_FRAC_MODE * IOCTL_SET_PLL_FRAC_DATA * IOCTL_SET_PLL_FRAC_DATA PLM has new EEMI APIs for PLL related operations. Call them instead of passing IOCTL API to PLM. For other IOCTL, ATF just pass through IOCTL request to PLM (Platform Loader and Manager). Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I96f8da46a4d3965c9291b7b2da96056408137839 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 34 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 11 +++++++ plat/xilinx/versal/pm_service/pm_svc_main.c | 9 ++++++ 4 files changed, 56 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index be28a41ae..dd69f0679 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -612,3 +612,37 @@ enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) return pm_ipi_send_non_blocking(primary_proc, payload); } + +/** + * pm_api_ioctl() - PM IOCTL API for device control and configs + * @device_id Device ID + * @ioctl_id ID of the requested IOCTL + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @value Returned output value + * + * This function calls IOCTL to firmware for device control and configuration. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, + uint32_t arg1, uint32_t arg2, uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + switch (ioctl_id) { + case IOCTL_SET_PLL_FRAC_MODE: + return pm_pll_set_mode(arg1, arg2); + case IOCTL_GET_PLL_FRAC_MODE: + return pm_pll_get_mode(arg1, value); + case IOCTL_SET_PLL_FRAC_DATA: + return pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2); + case IOCTL_GET_PLL_FRAC_DATA: + return pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value); + default: + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_IOCTL, device_id, + ioctl_id, arg1, arg2); + return pm_ipi_send_sync(primary_proc, payload, value, 1); + } +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 375199549..04074b18e 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -55,5 +55,7 @@ enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode); enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode); enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack); enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype); +enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, + uint32_t arg1, uint32_t arg2, uint32_t *value); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 248c7151f..fa3506607 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -41,6 +41,7 @@ #define PM_PINCTRL_SET_FUNCTION 31U #define PM_PINCTRL_CONFIG_PARAM_GET 32U #define PM_PINCTRL_CONFIG_PARAM_SET 33U +#define PM_IOCTL 34U #define PM_CLOCK_ENABLE 36U #define PM_CLOCK_DISABLE 37U #define PM_CLOCK_GETSTATE 38U @@ -55,6 +56,16 @@ #define PM_PLL_SET_MODE 50U #define PM_PLL_GET_MODE 51U +/* IOCTL IDs for clock driver */ +#define IOCTL_SET_PLL_FRAC_MODE 8 +#define IOCTL_GET_PLL_FRAC_MODE 9 +#define IOCTL_SET_PLL_FRAC_DATA 10 +#define IOCTL_GET_PLL_FRAC_DATA 11 + +/* Parameter ID for PLL IOCTLs */ +/* Fractional data portion for PLL */ +#define PM_PLL_PARAM_DATA 2 + /********************************************************************* * Enum definitions ********************************************************************/ diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index aa008ac9b..3aac79a86 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -182,6 +182,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_pinctrl_set_pin_param(pm_arg[0], pm_arg[1], pm_arg[2]); SMC_RET1(handle, (uint64_t)ret); + case PM_IOCTL: + { + uint32_t value; + + ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + case PM_CLOCK_ENABLE: ret = pm_clock_enable(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); From 26f1534ebdd5c91eb3581eae06dac78ba9043b95 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Mon, 21 Jan 2019 13:45:48 +0530 Subject: [PATCH 15/37] xilinx: move ipi mailbox svc to xilinx common As IPI mailbox service is common to both ZynqMP and Versal, move it to xilinx/common. Signed-off-by: Wendy Liang Signed-off-by: Jolly Shah Change-Id: I1a7008ccf7930829621147922d2c6d8d46df5502 --- .../ipi_mailbox_service/ipi_mailbox_svc.c | 2 +- .../ipi_mailbox_service/ipi_mailbox_svc.h | 2 +- plat/xilinx/zynqmp/platform.mk | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) rename plat/xilinx/{zynqmp => common}/ipi_mailbox_service/ipi_mailbox_svc.c (98%) rename plat/xilinx/{zynqmp => common}/ipi_mailbox_service/ipi_mailbox_svc.h (92%) diff --git a/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c similarity index 98% rename from plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c rename to plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c index c499d78e9..f53115885 100644 --- a/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c +++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.h b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h similarity index 92% rename from plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.h rename to plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h index 197c78819..10682d835 100644 --- a/plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.h +++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 33d648860..de4bf3a0b 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -55,9 +55,9 @@ endif PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ -Iinclude/plat/arm/common/aarch64/ \ -Iplat/xilinx/common/include/ \ + -Iplat/xilinx/common/ipi_mailbox_service/ \ -Iplat/xilinx/zynqmp/include/ \ -Iplat/xilinx/zynqmp/pm_service/ \ - -Iplat/xilinx/zynqmp/ipi_mailbox_service/ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ @@ -80,6 +80,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ lib/cpus/aarch64/aem_generic.S \ lib/cpus/aarch64/cortex_a53.S \ plat/common/plat_psci_common.c \ + plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \ plat/xilinx/common/pm_service/pm_ipi.c \ plat/xilinx/zynqmp/bl31_zynqmp_setup.c \ plat/xilinx/zynqmp/plat_psci.c \ @@ -92,5 +93,8 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c \ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c \ plat/xilinx/zynqmp/pm_service/pm_api_clock.c \ - plat/xilinx/zynqmp/pm_service/pm_client.c \ - plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c + plat/xilinx/zynqmp/pm_service/pm_client.c + +ifneq (${RESET_TO_BL31},1) + $(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.") +endif From 6e2f0d105d137257dbdae4d0ed73d813c6b03119 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Mon, 21 Jan 2019 13:45:49 +0530 Subject: [PATCH 16/37] xilinx: versal: enable ipi mailbox service Enable IPI mailbox service on versal platform. Signed-off-by: Wendy Liang Signed-off-by: Jolly Shah Change-Id: Idfba3bcd7e7b868133da0bc1d03c96db2d0bb1b7 --- plat/xilinx/versal/platform.mk | 2 ++ plat/xilinx/versal/sip_svc_setup.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk index eb1f0bb61..638f4fb21 100644 --- a/plat/xilinx/versal/platform.mk +++ b/plat/xilinx/versal/platform.mk @@ -38,6 +38,7 @@ VERSAL_CONSOLE ?= pl011 $(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE})) PLAT_INCLUDES := -Iplat/xilinx/common/include/ \ + -Iplat/xilinx/common/ipi_mailbox_service/ \ -Iplat/xilinx/versal/include/ \ -Iplat/xilinx/versal/pm_service/ @@ -58,6 +59,7 @@ 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/ipi_mailbox_service/ipi_mailbox_svc.c \ plat/xilinx/common/pm_service/pm_ipi.c \ plat/xilinx/versal/bl31_versal_setup.c \ plat/xilinx/versal/plat_psci.c \ diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c index 404c496a7..bc7d8b7af 100644 --- a/plat/xilinx/versal/sip_svc_setup.c +++ b/plat/xilinx/versal/sip_svc_setup.c @@ -9,6 +9,8 @@ #include #include #include + +#include "ipi_mailbox_svc.h" #include "pm_svc_main.h" /* SMC function IDs for SiP Service queries */ @@ -23,7 +25,9 @@ /* These macros are used to identify PM calls from the SMC function ID */ #define PM_FID_MASK 0xf000u #define PM_FID_VALUE 0u +#define IPI_FID_VALUE 0x1000u #define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE) +#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE) /* SiP Service UUID */ DEFINE_SVC_UUID2(versal_sip_uuid, @@ -64,6 +68,12 @@ uintptr_t sip_svc_smc_handler(uint32_t smc_fid, flags); } + /* Let IPI SMC handler deal with IPI-related requests */ + if (is_ipi_fid(smc_fid)) { + return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + /* Let PM SMC handler deal with PM-related requests */ switch (smc_fid) { case VERSAL_SIP_SVC_CALL_COUNT: From 4b0f32a411377bdbbc3d7913bde818afddde02ee Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Mon, 21 Jan 2019 17:56:48 +0530 Subject: [PATCH 17/37] xilinx: versal: Add support of PM_GET_TRUSTZONE_VERSION API PM_GET_TRUSTZONE_VERSION API is required to use zynqmp-firmware driver for versal. Add support of PM_GET_TRUSTZONE_VERSION API for versal. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Ie1c859890096024cc8be67386e3fd0f5f8a4385f --- plat/xilinx/versal/include/plat_pm_common.h | 4 ++++ plat/xilinx/versal/pm_service/pm_svc_main.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/plat/xilinx/versal/include/plat_pm_common.h b/plat/xilinx/versal/include/plat_pm_common.h index 6b202c746..2d0080168 100644 --- a/plat/xilinx/versal/include/plat_pm_common.h +++ b/plat/xilinx/versal/include/plat_pm_common.h @@ -19,4 +19,8 @@ #define PAYLOAD_ARG_CNT 6U #define PAYLOAD_ARG_SIZE 4U /* size in bytes */ +#define VERSAL_TZ_VERSION_MAJOR 1 +#define VERSAL_TZ_VERSION_MINOR 0 +#define VERSAL_TZ_VERSION ((VERSAL_TZ_VERSION_MAJOR << 16) | \ + VERSAL_TZ_VERSION_MINOR) #endif /* PLAT_PM_COMMON_H */ diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 3aac79a86..cb2ac5534 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -17,6 +17,8 @@ #include "pm_client.h" #include "pm_ipi.h" +#define PM_GET_TRUSTZONE_VERSION 0xa03 + /* pm_up = true - UP, pm_up = false - DOWN */ static bool pm_up; @@ -255,6 +257,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32)); } + case PM_GET_TRUSTZONE_VERSION: + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)VERSAL_TZ_VERSION << 32)); + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From ad19911c72db1da8f05d4f846b15fb5386290493 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Mon, 21 Jan 2019 17:56:49 +0530 Subject: [PATCH 18/37] xilinx: versal: Add PM_INIT_FINALIZE API for versal PM_INIT_FINALIZE is not required for versal. To use Linux Zynqmp PM driver for versal, handle PM_INIT_FINALIZE API in ATF for versal by always returning SUCCESS. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I6fe5445d78e713d70282ac8931ff8b17c96b2a14 --- plat/xilinx/versal/pm_service/pm_defs.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index fa3506607..e8a3f3dbd 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -35,6 +35,7 @@ #define PM_SET_REQUIREMENT 15U #define PM_RESET_ASSERT 17U #define PM_RESET_GET_STATUS 18U +#define PM_INIT_FINALIZE 21U #define PM_PINCTRL_REQUEST 28U #define PM_PINCTRL_RELEASE 29U #define PM_PINCTRL_GET_FUNCTION 30U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index cb2ac5534..9e7a5885e 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -152,6 +152,9 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ((uint64_t)reset_status << 32)); } + case PM_INIT_FINALIZE: + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS); + case PM_PINCTRL_REQUEST: ret = pm_pinctrl_request(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); From c56be55df319eac18c5d33ea6fe49ead80b18b0a Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 23 Jan 2019 14:18:51 +0530 Subject: [PATCH 19/37] xilinx: versal: Add request wakeup API Implement request wakeup API for versal. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I40a2a4ea85bf05623ac8a17ef4a6fa329babd27e --- plat/xilinx/versal/pm_service/pm_api_sys.c | 28 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 4 +++ 4 files changed, 35 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index dd69f0679..3e7e8d15e 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -159,6 +159,34 @@ enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, return pm_ipi_send(primary_proc, payload); } +/** + * pm_req_wakeup() - PM call for processor to wake up selected processor + * or subsystem + * @target Device ID of the processor or subsystem to wake up + * @set_address Resume address presence indicator + * 1 - resume address specified, 0 - otherwise + * @address Resume address + * @ack Flag to specify whether acknowledge requested + * + * This API function is either used to power up another APU core for SMP + * (by PSCI) or to power up an entirely different PU or subsystem, such + * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be + * automatically set by PMC. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, + uintptr_t address, uint8_t ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC to perform the wake of the PU */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REQ_WAKEUP, target, + set_address, address, ack); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + /** * pm_request_device() - Request a device * @device_id Device ID diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 04074b18e..91d3368f9 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -24,6 +24,8 @@ enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, unsigned int latency, unsigned int state); +enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, + uintptr_t address, uint8_t ack); enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, uint32_t qos, uint32_t ack); enum pm_ret_status pm_release_device(uint32_t device_id); diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index e8a3f3dbd..cfb1ca6cf 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -29,6 +29,7 @@ #define PM_SELF_SUSPEND 7U #define PM_FORCE_POWERDOWN 8U #define PM_ABORT_SUSPEND 9U +#define PM_REQ_WAKEUP 10U #define PM_SYSTEM_SHUTDOWN 12U #define PM_REQUEST_DEVICE 13U #define PM_RELEASE_DEVICE 14U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 9e7a5885e..bd3ebf3bd 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -107,6 +107,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_system_shutdown(pm_arg[0], pm_arg[1]); SMC_RET1(handle, (uint64_t)ret); + case PM_REQ_WAKEUP: + ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + case PM_REQUEST_DEVICE: ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); From 1f71e4fbfe6aaf349e764bc51ecdb3463536a82a Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Fri, 1 Feb 2019 17:25:19 +0530 Subject: [PATCH 20/37] xilinx: versal: Add query data API Add PM_QUERY_DATA API to pass query data EEMI call from Linux to PLM . Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I18735b72ab9cb62fb6cbc7582e77de6cb57f99b0 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 20 ++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 3 ++- plat/xilinx/versal/pm_service/pm_defs.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 10 ++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 3e7e8d15e..125134db8 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -641,6 +641,26 @@ enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) return pm_ipi_send_non_blocking(primary_proc, payload); } +/** +* pm_query_data() - PM API for querying firmware data +* @qid The type of data to query +* @arg1 Argument 1 to requested query data call +* @arg2 Argument 2 to requested query data call +* @arg3 Argument 3 to requested query data call +* @data Returned output data +* +* This function returns requested data. +*/ +enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t *data) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_QUERY_DATA, qid, arg1, + arg2, arg3); + return pm_ipi_send_sync(primary_proc, payload, data, 4); +} /** * pm_api_ioctl() - PM IOCTL API for device control and configs * @device_id Device ID diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 91d3368f9..ff3588236 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -59,5 +59,6 @@ enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack); enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype); enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, uint32_t arg1, uint32_t arg2, uint32_t *value); - +enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t *data); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index cfb1ca6cf..bd7430433 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -44,6 +44,7 @@ #define PM_PINCTRL_CONFIG_PARAM_GET 32U #define PM_PINCTRL_CONFIG_PARAM_SET 33U #define PM_IOCTL 34U +#define PM_QUERY_DATA 35U #define PM_CLOCK_ENABLE 36U #define PM_CLOCK_DISABLE 37U #define PM_CLOCK_GETSTATE 38U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index bd3ebf3bd..7f8e42fba 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -200,6 +200,16 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + case PM_QUERY_DATA: + { + uint32_t data[4] = { 0 }; + + ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], data); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)data[0] << 32), + (uint64_t)data[1] | ((uint64_t)data[2] << 32)); + } + case PM_CLOCK_ENABLE: ret = pm_clock_enable(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); From 25b1a91033ae3e4220c933333764c01c7a687c2d Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 27 Feb 2019 18:44:54 +0530 Subject: [PATCH 21/37] xilinx: versal: Add client wakeup API Implement client wakeup API for versal. Signed-off-by: Tejas Patel Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Change-Id: I31b1b362fe645a82f89ce2d698ee71eb00cf15dc --- plat/xilinx/versal/pm_service/pm_client.c | 40 +++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_client.h | 1 + 2 files changed, 41 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c index 636b719fd..b234e1bfa 100644 --- a/plat/xilinx/versal/pm_service/pm_client.c +++ b/plat/xilinx/versal/pm_service/pm_client.c @@ -18,6 +18,8 @@ #include #include "pm_client.h" +#define UNDEFINED_CPUID (~0) + DEFINE_BAKERY_LOCK(pm_client_secure_lock); static const struct pm_ipi apu_ipi = { @@ -80,6 +82,44 @@ void pm_client_abort_suspend(void) bakery_lock_release(&pm_client_secure_lock); } +/** + * pm_get_cpuid() - get the local cpu ID for a global node ID + * @nid: node id of the processor + * + * Return: the cpu ID (starting from 0) for the subsystem + */ +static unsigned int pm_get_cpuid(uint32_t nid) +{ + for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { + if (pm_procs_all[i].node_id == nid) + return i; + } + return UNDEFINED_CPUID; +} + +/** + * pm_client_wakeup() - Client-specific wakeup actions + * + * This function should contain any PU-specific actions + * required for waking up another APU core + */ +void pm_client_wakeup(const struct pm_proc *proc) +{ + unsigned int cpuid = pm_get_cpuid(proc->node_id); + + if (cpuid == UNDEFINED_CPUID) + return; + + bakery_lock_get(&pm_client_secure_lock); + + /* clear powerdown bit for affected cpu */ + uint32_t val = mmio_read_32(FPD_APU_PWRCTL); + val &= ~(proc->pwrdn_mask); + mmio_write_32(FPD_APU_PWRCTL, val); + + bakery_lock_release(&pm_client_secure_lock); +} + /** * pm_get_proc() - returns pointer to the proc structure * @cpuid: id of the cpu whose proc struct pointer should be returned diff --git a/plat/xilinx/versal/pm_service/pm_client.h b/plat/xilinx/versal/pm_service/pm_client.h index 228094e67..91f135c06 100644 --- a/plat/xilinx/versal/pm_service/pm_client.h +++ b/plat/xilinx/versal/pm_service/pm_client.h @@ -17,6 +17,7 @@ /* Functions to be implemented by each PU */ void pm_client_suspend(const struct pm_proc *proc, unsigned int state); +void pm_client_wakeup(const struct pm_proc *proc); void pm_client_abort_suspend(void); /* Global variables to be set in pm_client.c */ From 42cd77e386d4d0b847bcbbbe26fff315ed754087 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 23 Jan 2019 14:18:53 +0530 Subject: [PATCH 22/37] xilinx: versal: Add set wakeup source API Implement set wakeup source API to pass SMC call for set wakeup source to PLM (Platform Loader and Manager). Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: I654ce07235c0fc7dfcb81bf98820153255f61537 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 18 ++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 4 ++++ 4 files changed, 25 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 125134db8..5f3e30fff 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -694,3 +694,21 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, return pm_ipi_send_sync(primary_proc, payload, value, 1); } } + +/** + * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended + * @target Device id of the targeted PU or subsystem + * @wkup_node Device id of the wakeup peripheral + * @enable Enable or disable the specified peripheral as wake source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, + uint8_t enable) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_SET_WAKEUP_SOURCE, target, + wkup_device, enable); + return pm_ipi_send(primary_proc, payload); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index ff3588236..16722e72b 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -26,6 +26,8 @@ enum pm_ret_status pm_req_suspend(uint32_t target, unsigned int state); enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, uintptr_t address, uint8_t ack); +enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id, + uint8_t enable); enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, uint32_t qos, uint32_t ack); enum pm_ret_status pm_release_device(uint32_t device_id); diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index bd7430433..7d69699ba 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -30,6 +30,7 @@ #define PM_FORCE_POWERDOWN 8U #define PM_ABORT_SUSPEND 9U #define PM_REQ_WAKEUP 10U +#define PM_SET_WAKEUP_SOURCE 11U #define PM_SYSTEM_SHUTDOWN 12U #define PM_REQUEST_DEVICE 13U #define PM_RELEASE_DEVICE 14U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 7f8e42fba..94d1438cf 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -111,6 +111,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); SMC_RET1(handle, (uint64_t)ret); + case PM_SET_WAKEUP_SOURCE: + ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]); + SMC_RET1(handle, (uint64_t)ret); + case PM_REQUEST_DEVICE: ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); From 394a65aa96d6ce8cd55c0a824dc112d60ef97835 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 27 Feb 2019 18:44:57 +0530 Subject: [PATCH 23/37] xilinx: versal: Remove no_pmc ops to ON power domain Add PMC ops for power domain ON and remove no_pmc ops. Signed-off-by: Tejas Patel Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Change-Id: Id4308dfe124b60a751765beb3397d1b0071f14fc --- plat/xilinx/versal/plat_psci.c | 47 ++++++++++------------------------ 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c index de581bd0b..5e3b6f7fc 100644 --- a/plat/xilinx/versal/plat_psci.c +++ b/plat/xilinx/versal/plat_psci.c @@ -5,56 +5,35 @@ */ #include +#include #include #include #include #include +#include "pm_api_sys.h" +#include "pm_client.h" + static uintptr_t versal_sec_entry; -static int versal_nopmc_pwr_domain_on(u_register_t mpidr) +static int versal_pwr_domain_on(u_register_t mpidr) { - uint32_t r; unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); + const struct pm_proc *proc; VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); if (cpu_id == -1) return PSCI_E_INTERN_FAIL; - /* - * program RVBAR - */ - mmio_write_32(FPD_APU_RVBAR_L_0 + (cpu_id << 3), versal_sec_entry); - mmio_write_32(FPD_APU_RVBAR_H_0 + (cpu_id << 3), versal_sec_entry >> 32); + proc = pm_get_proc(cpu_id); - /* - * clear VINITHI - */ - r = mmio_read_32(FPD_APU_CONFIG_0); - r &= ~(1 << FPD_APU_CONFIG_0_VINITHI_SHIFT << cpu_id); - mmio_write_32(FPD_APU_CONFIG_0, r); + /* Send request to PMC to wake up selected ACPU core */ + pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFF) | 0x1, + versal_sec_entry >> 32, 0); - /* - * FIXME: Add power up sequence, By default it works - * now without the need of it as it was powered up by - * default. - */ - - /* - * clear power down request - */ - r = mmio_read_32(FPD_APU_PWRCTL); - r &= ~(1 << cpu_id); - mmio_write_32(FPD_APU_PWRCTL, r); - - /* - * release core reset - */ - r = mmio_read_32(CRF_RST_APU); - r &= ~((CRF_RST_APU_ACPU_PWRON_RESET | - CRF_RST_APU_ACPU_RESET) << cpu_id); - mmio_write_32(CRF_RST_APU, r); + /* Clear power down request */ + pm_client_wakeup(proc); return PSCI_E_SUCCESS; } @@ -69,7 +48,7 @@ void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) } static const struct plat_psci_ops versal_nopmc_psci_ops = { - .pwr_domain_on = versal_nopmc_pwr_domain_on, + .pwr_domain_on = versal_pwr_domain_on, .pwr_domain_on_finish = versal_pwr_domain_on_finish, }; From 5a8ffeabf97eb7fb1e1276cb967584af0ff7adbb Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 27 Feb 2019 18:44:55 +0530 Subject: [PATCH 24/37] 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 Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Change-Id: Ife908a45f32e2037c9c19e13211a8e4b373b8342 --- plat/xilinx/versal/aarch64/versal_common.c | 2 + plat/xilinx/versal/bl31_versal_setup.c | 4 + plat/xilinx/versal/include/plat_private.h | 2 + plat/xilinx/versal/include/platform_def.h | 2 +- plat/xilinx/versal/include/versal_def.h | 10 ++ plat/xilinx/versal/plat_psci.c | 142 +++++++++++++++++++++ plat/xilinx/versal/platform.mk | 9 +- plat/xilinx/versal/pm_service/pm_defs.h | 7 + 8 files changed, 175 insertions(+), 3 deletions(-) diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c index 2c6ff0537..29528da8a 100644 --- a/plat/xilinx/versal/aarch64/versal_common.c +++ b/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 } }; diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c index 0deff9006..6b56307af 100644 --- a/plat/xilinx/versal/bl31_versal_setup.c +++ b/plat/xilinx/versal/bl31_versal_setup.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -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), diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h index cb35be87e..e302096eb 100644 --- a/plat/xilinx/versal/include/plat_private.h +++ b/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); diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h index e61929cc1..c6be09e75 100644 --- a/plat/xilinx/versal/include/platform_def.h +++ b/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 diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index a77fa30d0..c2f78882d 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/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) diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c index 5e3b6f7fc..942ef01cc 100644 --- a/plat/xilinx/versal/plat_psci.c +++ b/plat/xilinx/versal/plat_psci.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include +#include #include #include #include @@ -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, }; /******************************************************************************* diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk index 638f4fb21..52d2c977b 100644 --- a/plat/xilinx/versal/platform.mk +++ b/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 \ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 7d69699ba..f090db538 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/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)) From 0abf4bba500e59dfe4b68468bb855e3897869e55 Mon Sep 17 00:00:00 2001 From: Saeed Nowshadi Date: Sun, 8 Dec 2019 23:35:35 -0800 Subject: [PATCH 25/37] xilinx: versal: Add PSCI APIs for system shutdown & reset Add following APIs in plat_psci to support system shutdown & reset: - versal_system_off - versal_system_reset Signed-off-by: Saeed Nowshadi Signed-off-by: Jolly Shah Change-Id: Ia2c1a19ded18984b393e1fdee760bf48b45e9902 --- plat/xilinx/versal/plat_psci.c | 31 ++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.c | 21 ++++++++++++++- plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 9 +++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c index 942ef01cc..39550858a 100644 --- a/plat/xilinx/versal/plat_psci.c +++ b/plat/xilinx/versal/plat_psci.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "pm_api_sys.h" #include "pm_client.h" @@ -114,6 +115,34 @@ void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) plat_versal_gic_cpuif_enable(); } +/** + * versal_system_off() - This function sends the system off request + * to firmware. This function does not return. + */ +static void __dead2 versal_system_off(void) +{ + /* Send the power down request to the PMC */ + pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN, + pm_get_shutdown_scope()); + + while (1) + wfi(); +} + +/** + * versal_system_reset() - This function sends the reset request + * to firmware for the system to reset. This function does not return. + */ +static void __dead2 versal_system_reset(void) +{ + /* Send the system reset request to the PMC */ + pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET, + pm_get_shutdown_scope()); + + while (1) + wfi(); +} + /** * versal_pwr_domain_off() - This function performs actions to turn off core * @@ -190,6 +219,8 @@ static const struct plat_psci_ops versal_nopmc_psci_ops = { .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, + .system_off = versal_system_off, + .system_reset = versal_system_reset, .validate_power_state = versal_validate_power_state, .get_sys_suspend_power_state = versal_get_sys_suspend_power_state, }; diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 5f3e30fff..99897ba9d 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -21,6 +21,19 @@ #define LIBPM_MODULE_ID 0x2 #define LOADER_MODULE_ID 0x7 +/* default shutdown/reboot scope is system(2) */ +static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM; + +/** + * pm_get_shutdown_scope() - Get the currently set shutdown scope + * + * @return Shutdown scope value + */ +unsigned int pm_get_shutdown_scope(void) +{ + return pm_shutdown_scope; +} + /** * Assigning of argument values into array elements. */ @@ -625,7 +638,7 @@ enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack) /** * pm_system_shutdown() - PM call to request a system shutdown or restart - * @type Shutdown or restart? 0=shutdown, 1=restart + * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system * * @return Returns status, either success or error+reason @@ -634,6 +647,12 @@ enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) { uint32_t payload[PAYLOAD_ARG_CNT]; + if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) { + /* Setting scope for subsequent PSCI reboot or shutdown */ + pm_shutdown_scope = subtype; + return PM_RET_SUCCESS; + } + /* Send request to the PMC */ PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SYSTEM_SHUTDOWN, type, subtype); diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 16722e72b..b1ad3f276 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -63,4 +63,6 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, uint32_t arg1, uint32_t arg2, uint32_t *value); enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t *data); +unsigned int pm_get_shutdown_scope(void); + #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index f090db538..626fa3916 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -77,6 +77,15 @@ /* Fractional data portion for PLL */ #define PM_PLL_PARAM_DATA 2 +/* System shutdown macros */ +#define XPM_SHUTDOWN_TYPE_SHUTDOWN 0U +#define XPM_SHUTDOWN_TYPE_RESET 1U +#define XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY 2U + +#define XPM_SHUTDOWN_SUBTYPE_RST_SUBSYSTEM 0U +#define XPM_SHUTDOWN_SUBTYPE_RST_PS_ONLY 1U +#define XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM 2U + /********************************************************************* * Enum definitions ********************************************************************/ From 89224531b43f4a2396a0b5a9ab34349bd7c58b06 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 4 Mar 2019 11:09:40 +0530 Subject: [PATCH 26/37] plat: xilinx: versal: Add GET_CALLBACK_DATA function Add GET_CALLBACK_DATA function to get IPI callback data in Linux during init suspend callback. Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Change-Id: Ieb60e561b5f656611f0702c43ba6a4296a012651 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 16 ++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 11 +++++++++++ 3 files changed, 28 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 99897ba9d..216bc9801 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -312,6 +312,22 @@ enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status) return pm_ipi_send_sync(primary_proc, payload, status, 1); } +/** + * pm_get_callbackdata() - Read from IPI response buffer + * @data - array of PAYLOAD_ARG_CNT elements + * + * Read value from ipi buffer response buffer. + */ +void pm_get_callbackdata(uint32_t *data, size_t count) +{ + /* Return if interrupt is not from PMU */ + if (!pm_ipi_irq_status(primary_proc)) + return; + + pm_ipi_buff_read_callb(data, count); + pm_ipi_irq_clear(primary_proc); +} + /** * pm_pinctrl_request() - Request a pin * @pin Pin ID diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index b1ad3f276..282c175a8 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -36,6 +36,7 @@ enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response); enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert); enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status); +void pm_get_callbackdata(uint32_t *data, size_t count); enum pm_ret_status pm_pinctrl_request(uint32_t pin); enum pm_ret_status pm_pinctrl_release(uint32_t pin); enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function); diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 94d1438cf..8140b6644 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -17,6 +17,7 @@ #include "pm_client.h" #include "pm_ipi.h" +#define PM_GET_CALLBACK_DATA 0xa01 #define PM_GET_TRUSTZONE_VERSION 0xa03 /* pm_up = true - UP, pm_up = false - DOWN */ @@ -163,6 +164,16 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, case PM_INIT_FINALIZE: SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS); + case PM_GET_CALLBACK_DATA: + { + uint32_t result[4] = {0}; + + pm_get_callbackdata(result, sizeof(result)); + SMC_RET2(handle, + (uint64_t)result[0] | ((uint64_t)result[1] << 32), + (uint64_t)result[2] | ((uint64_t)result[3] << 32)); + } + case PM_PINCTRL_REQUEST: ret = pm_pinctrl_request(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); From 6e82cd8c9b37ad6226523e88829ecba776b15bc8 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Wed, 27 Feb 2019 18:44:56 +0530 Subject: [PATCH 27/37] xilinx: versal: Implement set wakeup source for client Add support to set wakeup source for APU while suspending. Signed-off-by: Tejas Patel Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Change-Id: I4809fd83a710def8144fdad74990c45e62b8fdf3 --- plat/xilinx/versal/pm_service/pm_client.c | 114 ++++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_defs.h | 4 + 2 files changed, 118 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c index b234e1bfa..5b47838e9 100644 --- a/plat/xilinx/versal/pm_service/pm_client.c +++ b/plat/xilinx/versal/pm_service/pm_client.c @@ -9,16 +9,22 @@ * for getting information about and changing state of the APU. */ +#include #include #include #include #include #include +#include #include +#include #include +#include "pm_api_sys.h" #include "pm_client.h" #define UNDEFINED_CPUID (~0) +#define IRQ_MAX 142 +#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1) DEFINE_BAKERY_LOCK(pm_client_secure_lock); @@ -44,6 +50,111 @@ static const struct pm_proc pm_procs_all[] = { const struct pm_proc *primary_proc = &pm_procs_all[0]; +/* Interrupt to PM node index map */ +static enum pm_device_node_idx irq_node_map[IRQ_MAX + 1] = { + [13] = XPM_NODEIDX_DEV_GPIO, + [14] = XPM_NODEIDX_DEV_I2C_0, + [15] = XPM_NODEIDX_DEV_I2C_1, + [16] = XPM_NODEIDX_DEV_SPI_0, + [17] = XPM_NODEIDX_DEV_SPI_1, + [18] = XPM_NODEIDX_DEV_UART_0, + [19] = XPM_NODEIDX_DEV_UART_1, + [20] = XPM_NODEIDX_DEV_CAN_FD_0, + [21] = XPM_NODEIDX_DEV_CAN_FD_1, + [22] = XPM_NODEIDX_DEV_USB_0, + [23] = XPM_NODEIDX_DEV_USB_0, + [24] = XPM_NODEIDX_DEV_USB_0, + [25] = XPM_NODEIDX_DEV_USB_0, + [26] = XPM_NODEIDX_DEV_USB_0, + [37] = XPM_NODEIDX_DEV_TTC_0, + [38] = XPM_NODEIDX_DEV_TTC_0, + [39] = XPM_NODEIDX_DEV_TTC_0, + [40] = XPM_NODEIDX_DEV_TTC_1, + [41] = XPM_NODEIDX_DEV_TTC_1, + [42] = XPM_NODEIDX_DEV_TTC_1, + [43] = XPM_NODEIDX_DEV_TTC_2, + [44] = XPM_NODEIDX_DEV_TTC_2, + [45] = XPM_NODEIDX_DEV_TTC_2, + [46] = XPM_NODEIDX_DEV_TTC_3, + [47] = XPM_NODEIDX_DEV_TTC_3, + [48] = XPM_NODEIDX_DEV_TTC_3, + [56] = XPM_NODEIDX_DEV_GEM_0, + [57] = XPM_NODEIDX_DEV_GEM_0, + [58] = XPM_NODEIDX_DEV_GEM_1, + [59] = XPM_NODEIDX_DEV_GEM_1, + [60] = XPM_NODEIDX_DEV_ADMA_0, + [61] = XPM_NODEIDX_DEV_ADMA_1, + [62] = XPM_NODEIDX_DEV_ADMA_2, + [63] = XPM_NODEIDX_DEV_ADMA_3, + [64] = XPM_NODEIDX_DEV_ADMA_4, + [65] = XPM_NODEIDX_DEV_ADMA_5, + [66] = XPM_NODEIDX_DEV_ADMA_6, + [67] = XPM_NODEIDX_DEV_ADMA_7, + [74] = XPM_NODEIDX_DEV_USB_0, + [126] = XPM_NODEIDX_DEV_SDIO_0, + [127] = XPM_NODEIDX_DEV_SDIO_0, + [128] = XPM_NODEIDX_DEV_SDIO_1, + [129] = XPM_NODEIDX_DEV_SDIO_1, + [142] = XPM_NODEIDX_DEV_RTC, +}; + +/** + * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number + * @irq: Interrupt number + * + * Return: PM node index corresponding to the specified interrupt + */ +static enum pm_device_node_idx irq_to_pm_node_idx(unsigned int irq) +{ + assert(irq <= IRQ_MAX); + return irq_node_map[irq]; +} + +/** + * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as + * wake sources in the LibPM. + */ +static void pm_client_set_wakeup_sources(void) +{ + uint32_t reg_num; + uint32_t device_id; + uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX]; + uintptr_t isenabler1 = PLAT_VERSAL_GICD_BASE + GICD_ISENABLER + 4; + + zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set)); + + for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) { + uint32_t base_irq = reg_num << ISENABLER_SHIFT; + uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2)); + + if (!reg) + continue; + + while (reg) { + enum pm_device_node_idx node_idx; + uint32_t idx, ret, irq, lowest_set = reg & (-reg); + + idx = __builtin_ctz(lowest_set); + irq = base_irq + idx; + + if (irq > IRQ_MAX) + break; + + node_idx = irq_to_pm_node_idx(irq); + reg &= ~lowest_set; + + if ((node_idx != XPM_NODEIDX_DEV_MIN) && + (!pm_wakeup_nodes_set[node_idx])) { + /* Get device ID from node index */ + device_id = PERIPH_DEVID(node_idx); + ret = pm_set_wakeup_source(XPM_DEVID_ACPU_0, + device_id, 1); + pm_wakeup_nodes_set[node_idx] = !ret; + } + } + } +} + /** * pm_client_suspend() - Client-specific suspend actions * @@ -55,6 +166,9 @@ void pm_client_suspend(const struct pm_proc *proc, unsigned int state) { bakery_lock_get(&pm_client_secure_lock); + if (state == PM_STATE_SUSPEND_TO_RAM) + pm_client_set_wakeup_sources(); + /* Set powerdown request */ mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | proc->pwrdn_mask); diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 626fa3916..281494a76 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -29,6 +29,10 @@ #define XPM_DEVID_ACPU_0 APU_DEVID(XPM_NODEIDX_DEV_ACPU_0) #define XPM_DEVID_ACPU_1 APU_DEVID(XPM_NODEIDX_DEV_ACPU_1) +#define PERIPH_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, \ + XPM_NODESUBCL_DEV_PERIPH, \ + XPM_NODETYPE_DEV_PERIPH, (IDX)) + /* PM API ids */ #define PM_GET_API_VERSION 1U #define PM_GET_DEVICE_STATUS 3U From 39db98efc96afc853b55e98d1b0587c58066e5c0 Mon Sep 17 00:00:00 2001 From: Ravi Patel Date: Wed, 6 Mar 2019 12:34:46 +0530 Subject: [PATCH 28/37] xilinx: versal: Add feature check API Add API to check availability of given API in ATF as well as platform management controller and returns the supported version number. Signed-off-by: Ravi Patel Signed-off-by: Jolly Shah Change-Id: I608b38f60b36c4d105b7a205ecb8b02de0c00f3c --- plat/xilinx/versal/pm_service/pm_api_sys.c | 70 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 +- plat/xilinx/versal/pm_service/pm_defs.h | 9 +++ plat/xilinx/versal/pm_service/pm_svc_main.c | 11 +++- 4 files changed, 88 insertions(+), 4 deletions(-) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 216bc9801..54fd6e118 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -747,3 +747,73 @@ enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, wkup_device, enable); return pm_ipi_send(primary_proc, payload); } + +/** + * pm_feature_check() - Returns the supported API version if supported + * @api_id API ID to check + * @value Returned supported API version + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) +{ + uint32_t payload[PAYLOAD_ARG_CNT], fw_api_version; + uint32_t status; + + switch (api_id) { + case PM_GET_CALLBACK_DATA: + case PM_GET_TRUSTZONE_VERSION: + case PM_INIT_FINALIZE: + *version = (PM_API_BASE_VERSION << 16); + return PM_RET_SUCCESS; + case PM_GET_API_VERSION: + case PM_GET_DEVICE_STATUS: + case PM_REQ_SUSPEND: + case PM_SELF_SUSPEND: + case PM_FORCE_POWERDOWN: + case PM_ABORT_SUSPEND: + case PM_REQ_WAKEUP: + case PM_SET_WAKEUP_SOURCE: + case PM_SYSTEM_SHUTDOWN: + case PM_REQUEST_DEVICE: + case PM_RELEASE_DEVICE: + case PM_SET_REQUIREMENT: + case PM_RESET_ASSERT: + case PM_RESET_GET_STATUS: + case PM_PINCTRL_REQUEST: + case PM_PINCTRL_RELEASE: + case PM_PINCTRL_GET_FUNCTION: + case PM_PINCTRL_SET_FUNCTION: + case PM_PINCTRL_CONFIG_PARAM_GET: + case PM_PINCTRL_CONFIG_PARAM_SET: + case PM_IOCTL: + case PM_QUERY_DATA: + case PM_CLOCK_ENABLE: + case PM_CLOCK_DISABLE: + case PM_CLOCK_GETSTATE: + case PM_CLOCK_SETDIVIDER: + case PM_CLOCK_GETDIVIDER: + case PM_CLOCK_SETPARENT: + case PM_CLOCK_GETPARENT: + case PM_PLL_SET_PARAMETER: + case PM_PLL_GET_PARAMETER: + case PM_PLL_SET_MODE: + case PM_PLL_GET_MODE: + case PM_FEATURE_CHECK: + *version = (PM_API_BASE_VERSION << 16); + break; + default: + *version = 0U; + return PM_RET_ERROR_NOFEATURE; + } + + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_FEATURE_CHECK, api_id); + + status = pm_ipi_send_sync(primary_proc, payload, &fw_api_version, 1); + if (status != PM_RET_SUCCESS) + return status; + + *version |= fw_api_version; + + return PM_RET_SUCCESS; +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 282c175a8..4e884e087 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -65,5 +65,5 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t *data); unsigned int pm_get_shutdown_scope(void); - +enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 281494a76..a7b0a0297 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -33,6 +33,12 @@ XPM_NODESUBCL_DEV_PERIPH, \ XPM_NODETYPE_DEV_PERIPH, (IDX)) +#define PM_GET_CALLBACK_DATA 0xa01 +#define PM_GET_TRUSTZONE_VERSION 0xa03 + +/* PM API Versions */ +#define PM_API_BASE_VERSION 1U + /* PM API ids */ #define PM_GET_API_VERSION 1U #define PM_GET_DEVICE_STATUS 3U @@ -70,6 +76,7 @@ #define PM_PLL_GET_PARAMETER 49U #define PM_PLL_SET_MODE 50U #define PM_PLL_GET_MODE 51U +#define PM_FEATURE_CHECK 63U /* IOCTL IDs for clock driver */ #define IOCTL_SET_PLL_FRAC_MODE 8 @@ -121,6 +128,7 @@ typedef enum { * @PM_RET_SUCCESS: success * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated) * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated) + * @PM_RET_ERROR_NOFEATURE: feature is not available * @PM_RET_ERROR_INTERNAL: internal error * @PM_RET_ERROR_CONFLICT: conflict * @PM_RET_ERROR_ACCESS: access rights violation @@ -134,6 +142,7 @@ enum pm_ret_status { PM_RET_SUCCESS, PM_RET_ERROR_ARGS = 1, PM_RET_ERROR_NOTSUPPORTED = 4, + PM_RET_ERROR_NOFEATURE = 19, PM_RET_ERROR_INTERNAL = 2000, PM_RET_ERROR_CONFLICT = 2001, PM_RET_ERROR_ACCESS = 2002, diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 8140b6644..b5a678332 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -17,9 +17,6 @@ #include "pm_client.h" #include "pm_ipi.h" -#define PM_GET_CALLBACK_DATA 0xa01 -#define PM_GET_TRUSTZONE_VERSION 0xa03 - /* pm_up = true - UP, pm_up = false - DOWN */ static bool pm_up; @@ -293,6 +290,14 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | ((uint64_t)VERSAL_TZ_VERSION << 32)); + case PM_FEATURE_CHECK: + { + uint32_t version; + + ret = pm_feature_check(pm_arg[0], &version); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)version << 32)); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From e4c54c0d2d54599db4b0f9e0e6f644864b05dd3e Mon Sep 17 00:00:00 2001 From: Jolly Shah Date: Fri, 22 Mar 2019 05:33:39 +0530 Subject: [PATCH 29/37] plat: xilinx: versal: Add load Pdi API support This patch adds support for load pdi api to enable loading pdi from linux. Signed-off-by: Jolly Shah Change-Id: I48549e276e1f7b9be45a0bebf559f73bd09d5f69 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 25 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 2 ++ plat/xilinx/versal/pm_service/pm_defs.h | 3 +++ plat/xilinx/versal/pm_service/pm_svc_main.c | 6 +++++ 4 files changed, 36 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 54fd6e118..e48fbf576 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -802,6 +802,9 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) case PM_FEATURE_CHECK: *version = (PM_API_BASE_VERSION << 16); break; + case PM_LOAD_PDI: + *version = (PM_API_BASE_VERSION << 16); + return PM_RET_SUCCESS; default: *version = 0U; return PM_RET_ERROR_NOFEATURE; @@ -817,3 +820,25 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) return PM_RET_SUCCESS; } + +/** + * pm_load_pdi() - Load the PDI + * + * This function provides support to load PDI from linux + * + * src: Source device of pdi(DDR, OCM, SD etc) + * address_low: lower 32-bit Linear memory space address + * address_high: higher 32-bit Linear memory space address + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_load_pdi(uint32_t src, + uint32_t address_low, uint32_t address_high) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, PM_LOAD_PDI, src, + address_high, address_low); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 4e884e087..5effbb683 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -66,4 +66,6 @@ enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t *data); unsigned int pm_get_shutdown_scope(void); enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version); +enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, + uint32_t address_high); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index a7b0a0297..892804d7f 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -78,6 +78,9 @@ #define PM_PLL_GET_MODE 51U #define PM_FEATURE_CHECK 63U +/* Loader API ids */ +#define PM_LOAD_PDI 0x701U + /* IOCTL IDs for clock driver */ #define IOCTL_SET_PLL_FRAC_MODE 8 #define IOCTL_GET_PLL_FRAC_MODE 9 diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index b5a678332..bbe8097a8 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -298,6 +298,12 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)version << 32)); } + case PM_LOAD_PDI: + { + ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2]); + SMC_RET1(handle, (uint64_t)ret); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From ea6e1c39423301b49b304fc474c649e519644fa4 Mon Sep 17 00:00:00 2001 From: Ravi Patel Date: Mon, 12 Aug 2019 03:17:54 -0700 Subject: [PATCH 30/37] plat: versal: Add Get_ChipID API Add support for Get_ChipID API in Versal which calls corresponding LibPM API. Signed-off-by: Ravi Patel Acked-by: Jolly Shah Signed-off-by: Jolly Shah Change-Id: I25c4b301721d7989d982ac376c59195c55564022 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 17 +++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 1 + plat/xilinx/versal/pm_service/pm_defs.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 9 +++++++++ 4 files changed, 28 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index e48fbf576..a4c0b285e 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -748,6 +748,23 @@ enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, return pm_ipi_send(primary_proc, payload); } +/** + * pm_get_chipid() - Read silicon ID registers + * @value Buffer for return values. Must be large enough + * to hold 8 bytes. + * + * @return Returns silicon ID registers + */ +enum pm_ret_status pm_get_chipid(uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_CHIPID); + + return pm_ipi_send_sync(primary_proc, payload, value, 2); +} + /** * pm_feature_check() - Returns the supported API version if supported * @api_id API ID to check diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 5effbb683..995c49efa 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -65,6 +65,7 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t *data); unsigned int pm_get_shutdown_scope(void); +enum pm_ret_status pm_get_chipid(uint32_t *value); enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version); enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, uint32_t address_high); diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 892804d7f..7d4066bdc 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -55,6 +55,7 @@ #define PM_RESET_ASSERT 17U #define PM_RESET_GET_STATUS 18U #define PM_INIT_FINALIZE 21U +#define PM_GET_CHIPID 24U #define PM_PINCTRL_REQUEST 28U #define PM_PINCTRL_RELEASE 29U #define PM_PINCTRL_GET_FUNCTION 30U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index bbe8097a8..d2460131f 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -290,6 +290,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | ((uint64_t)VERSAL_TZ_VERSION << 32)); + case PM_GET_CHIPID: + { + uint32_t result[2]; + + ret = pm_get_chipid(result); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32), + result[1]); + } + case PM_FEATURE_CHECK: { uint32_t version; From f50828d52ec6fc7c20459d5ce581ffa927347030 Mon Sep 17 00:00:00 2001 From: Saeed Nowshadi Date: Mon, 3 Jun 2019 10:22:35 -0700 Subject: [PATCH 31/37] xilinx: versal: Add support for PM_GET_OPERATING_CHARACTERISTIC EEMI call This patch adds EEMI support for PM_GET_OPERATING_CHARACTERISTIC api id. This interface obtains operating characteristic of a device from PMC firmware. The 'power', 'temperature', and 'latency' characteristic are the options that are supported. Signed-off-by: Saeed Nowshadi Signed-off-by: Jolly Shah Change-Id: If30959ba6a3a778a17df2a4281c2c09832cf7e92 --- plat/xilinx/versal/pm_service/pm_api_sys.c | 24 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_api_sys.h | 3 +++ plat/xilinx/versal/pm_service/pm_defs.h | 7 ++++++ plat/xilinx/versal/pm_service/pm_svc_main.c | 8 +++++++ 4 files changed, 42 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index a4c0b285e..dbe94e624 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -785,6 +785,7 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) return PM_RET_SUCCESS; case PM_GET_API_VERSION: case PM_GET_DEVICE_STATUS: + case PM_GET_OP_CHARACTERISTIC: case PM_REQ_SUSPEND: case PM_SELF_SUSPEND: case PM_FORCE_POWERDOWN: @@ -859,3 +860,26 @@ enum pm_ret_status pm_load_pdi(uint32_t src, address_high, address_low); return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } + +/** + * pm_get_op_characteristic() - PM call to request operating characteristics + * of a device + * @device_id Device id + * @type Type of the operating characteristic + * (power, temperature and latency) + * @result Returns the operating characteristic for the requested device, + * specified by the type + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_op_characteristic(uint32_t device_id, + enum pm_opchar_type type, + uint32_t *result) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_GET_OP_CHARACTERISTIC, + device_id, type); + return pm_ipi_send_sync(primary_proc, payload, result, 1); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 995c49efa..4de592a2f 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -69,4 +69,7 @@ enum pm_ret_status pm_get_chipid(uint32_t *value); enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version); enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, uint32_t address_high); +enum pm_ret_status pm_get_op_characteristic(uint32_t device_id, + enum pm_opchar_type type, + uint32_t *result); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 7d4066bdc..966b00bb5 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -42,6 +42,7 @@ /* PM API ids */ #define PM_GET_API_VERSION 1U #define PM_GET_DEVICE_STATUS 3U +#define PM_GET_OP_CHARACTERISTIC 4U #define PM_REQ_SUSPEND 6U #define PM_SELF_SUSPEND 7U #define PM_FORCE_POWERDOWN 8U @@ -112,6 +113,12 @@ enum pm_abort_reason { ABORT_REASON_UNKNOWN, }; +enum pm_opchar_type { + PM_OPCHAR_TYPE_POWER = 1, + PM_OPCHAR_TYPE_TEMP, + PM_OPCHAR_TYPE_LATENCY, +}; + /** * Subsystem IDs */ diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index d2460131f..a3a9f4316 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -313,6 +313,14 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret); } + case PM_GET_OP_CHARACTERISTIC: + { + uint32_t result; + + ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32)); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From c959c479ebda1879af5b24ce55da5bd093dca6b8 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Sat, 27 Apr 2019 11:23:20 +0530 Subject: [PATCH 32/37] arm64: versal: Adjust cpu clock for versal virtual This patch modifies cpu clock for Xilinx Versal virtual platform in order to keep same as used by QEMU. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Jolly Shah Change-Id: I169d082462d7ce94a82c62966ab9eb122c5a3fee --- plat/xilinx/versal/include/versal_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index c2f78882d..c08928a44 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -87,7 +87,7 @@ # define PLATFORM_NAME "Versal Virt" # define VERSAL_UART_CLOCK 25000000 # define VERSAL_UART_BAUDRATE 115200 -# define VERSAL_CPU_CLOCK 62500000 +# define VERSAL_CPU_CLOCK 2720000 #endif /* Access control register defines */ From f8a650c15324efc3f8df421637cd221035701152 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 25 Jun 2019 17:48:27 +0530 Subject: [PATCH 33/37] plat: xilinx: versal: Dont set IOU switch clock The IOU switch clock will be set by PLM during boot so there is no need to set here and hence this patch removes it. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Jolly Shah Change-Id: I1512708411eb07a07c1a8fbd66575efee975431a --- plat/xilinx/versal/aarch64/versal_common.c | 4 ---- plat/xilinx/versal/include/versal_def.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c index 29528da8a..825421e29 100644 --- a/plat/xilinx/versal/aarch64/versal_common.c +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -46,10 +46,6 @@ void versal_config_setup(void) versal_print_platform_name(); - mmio_write_32(VERSAL_CRL_IOU_SWITCH_CTRL, - VERSAL_IOU_SWITCH_CTRL_CLKACT_BIT | - (0x20 << VERSAL_IOU_SWITCH_CTRL_DIVISOR0_SHIFT)); - /* Global timer init - Program time stamp reference clk */ val = mmio_read_32(VERSAL_CRL_TIMESTAMP_REF_CTRL); val |= VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT; diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index c08928a44..a1479a10c 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -35,13 +35,10 @@ /* CRL */ #define VERSAL_CRL 0xFF5E0000 -#define VERSAL_CRL_IOU_SWITCH_CTRL (VERSAL_CRL + 0x114) #define VERSAL_CRL_TIMESTAMP_REF_CTRL (VERSAL_CRL + 0x14C) #define VERSAL_CRL_RST_TIMESTAMP_OFFSET (VERSAL_CRL + 0x348) #define VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1 << 25) -#define VERSAL_IOU_SWITCH_CTRL_CLKACT_BIT (1 << 25) -#define VERSAL_IOU_SWITCH_CTRL_DIVISOR0_SHIFT 8 /* IOU SCNTRS */ #define VERSAL_IOU_SCNTRS 0xFF140000 From 29af4789759714db41d10e3c80d0b00e14916d54 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Mon, 25 Nov 2019 01:47:48 -0700 Subject: [PATCH 34/37] versal: Increase OCM memory size for DEBUG builds ATF can't fit in current OCM size when the DEBUG is enabled, so increase the OCM size to use 128Kb. Signed-off-by: Venkatesh Yadav Abbarapu Signed-off-by: Jolly Shah Change-Id: I2ebfd1f2e9db9c0b28770aea7f8fbf1a8a15787a --- plat/xilinx/versal/include/platform_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h index c6be09e75..bcc7a9364 100644 --- a/plat/xilinx/versal/include/platform_def.h +++ b/plat/xilinx/versal/include/platform_def.h @@ -31,7 +31,7 @@ * little space for growth. */ #ifndef VERSAL_ATF_MEM_BASE -# define BL31_BASE 0xfffea000 +# define BL31_BASE 0xfffe0000 # define BL31_LIMIT 0xffffffff #else # define BL31_BASE (VERSAL_ATF_MEM_BASE) From d69bbd0e80d07d4c9008a0666e192491ddf52e43 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Fri, 3 May 2019 16:35:25 +0530 Subject: [PATCH 35/37] xilinx: versal: Wire silicon default setup Add new option for serial and default clock setup. Signed-off-by: Michal Simek Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Jolly Shah Change-Id: I0ca7ad51637cdaa6bb891f22c53595d20da7236a --- plat/xilinx/versal/include/versal_def.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index a1479a10c..94bd321b8 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -19,6 +19,7 @@ /* List all supported platforms */ #define VERSAL_PLATFORM_ID_versal_virt 1 +#define VERSAL_PLATFORM_ID_silicon 4 #define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM) @@ -85,6 +86,11 @@ # define VERSAL_UART_CLOCK 25000000 # define VERSAL_UART_BAUDRATE 115200 # define VERSAL_CPU_CLOCK 2720000 +#elif VERSAL_PLATFORM_IS(silicon) +# define PLATFORM_NAME "Versal Silicon" +# define VERSAL_UART_CLOCK 100000000 +# define VERSAL_UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 100000000 #endif /* Access control register defines */ From 7b9f0cfd8c7944635ff84520ba7fa32c470b0cd8 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 10 Jul 2019 16:15:19 +0530 Subject: [PATCH 36/37] plat: xilinx: versal: Make silicon default build target This patch makes default build target as silicon instead of QEMU. The default can be overwritten by specifying it through build flag VERSAL_PLATFORM. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Jolly Shah Change-Id: Ia4cb1df1f206db3e514e8ce969acca875e973ace --- docs/plat/xilinx-versal.rst | 2 +- plat/xilinx/versal/platform.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst index 231286e7e..95c89a8b2 100644 --- a/docs/plat/xilinx-versal.rst +++ b/docs/plat/xilinx-versal.rst @@ -14,7 +14,7 @@ To build: make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 ``` -To build ATF for different platform (for now its just versal virtual "versal_virt") +To build ATF for different platform (supported are "silicon"(default) and "versal_virt") ```bash make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31 ``` diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk index 52d2c977b..7a8bfa31a 100644 --- a/plat/xilinx/versal/platform.mk +++ b/plat/xilinx/versal/platform.mk @@ -31,7 +31,7 @@ ifdef VERSAL_BL32_MEM_BASE $(eval $(call add_define,VERSAL_BL32_MEM_SIZE)) endif -VERSAL_PLATFORM ?= versal_virt +VERSAL_PLATFORM ?= silicon $(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM})) VERSAL_CONSOLE ?= pl011 From 92c30ac35b298bb4049778ed1c0b95713e44e44c Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Fri, 10 Jan 2020 03:08:40 -0800 Subject: [PATCH 37/37] plat: xilinx: Move pm_client.h to common directory Move pm_client.h to common directory to avoid duplication of function declaration. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Change-Id: Iea542e681f42db089cccd9b24d286ac8f0a2ce35 --- .../pm_service => common/include}/pm_client.h | 11 +++++--- plat/xilinx/versal/pm_service/pm_client.h | 26 ------------------- 2 files changed, 7 insertions(+), 30 deletions(-) rename plat/xilinx/{zynqmp/pm_service => common/include}/pm_client.h (88%) delete mode 100644 plat/xilinx/versal/pm_service/pm_client.h diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.h b/plat/xilinx/common/include/pm_client.h similarity index 88% rename from plat/xilinx/zynqmp/pm_service/pm_client.h rename to plat/xilinx/common/include/pm_client.h index adbb76f9b..e91bb8f6c 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.h +++ b/plat/xilinx/common/include/pm_client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -19,11 +19,14 @@ void pm_client_suspend(const struct pm_proc *proc, unsigned int state); void pm_client_abort_suspend(void); void pm_client_wakeup(const struct pm_proc *proc); -enum pm_ret_status set_ocm_retention(void); -enum pm_ret_status pm_set_suspend_mode(uint32_t mode); -const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid); /* Global variables to be set in pm_client.c */ extern const struct pm_proc *primary_proc; +#ifndef VERSAL_PLATFORM +enum pm_ret_status set_ocm_retention(void); +enum pm_ret_status pm_set_suspend_mode(uint32_t mode); +const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid); +#endif + #endif /* PM_CLIENT_H */ diff --git a/plat/xilinx/versal/pm_service/pm_client.h b/plat/xilinx/versal/pm_service/pm_client.h deleted file mode 100644 index 91f135c06..000000000 --- a/plat/xilinx/versal/pm_service/pm_client.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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" - -/* Functions to be implemented by each PU */ -void pm_client_suspend(const struct pm_proc *proc, unsigned int state); -void pm_client_wakeup(const struct pm_proc *proc); -void pm_client_abort_suspend(void); - -/* Global variables to be set in pm_client.c */ -extern const struct pm_proc *primary_proc; - -#endif /* PM_CLIENT_H */