From 8b901406572fb1ea115613ec01d0b04e74d9526b Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Apr 2016 13:26:41 -0700 Subject: [PATCH 01/18] zynqmp: Remove unused/redundant #includes Signed-off-by: Soren Brinkmann Acked-by: Michal Simek --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 4 ---- plat/xilinx/zynqmp/plat_topology.c | 3 --- plat/xilinx/zynqmp/tsp/tsp_plat_setup.c | 2 -- 3 files changed, 9 deletions(-) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index 0a878c30e4..429eec27e4 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -28,12 +28,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include -#include #include -#include #include #include #include "../zynqmp_private.h" diff --git a/plat/xilinx/zynqmp/plat_topology.c b/plat/xilinx/zynqmp/plat_topology.c index 34e7b53b66..e1263e0eac 100644 --- a/plat/xilinx/zynqmp/plat_topology.c +++ b/plat/xilinx/zynqmp/plat_topology.c @@ -28,9 +28,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include - static const unsigned char plat_power_domain_tree_desc[] = {1, 4}; const unsigned char *plat_get_power_domain_tree_desc(void) diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c index 291ccbac09..d600450dd6 100644 --- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c +++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c @@ -32,9 +32,7 @@ #include #include #include -#include #include -#include "../zynqmp_def.h" #include "../zynqmp_private.h" /* From 0a48e2bde8f346a6af7f52de40b7208fc0981739 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Apr 2016 15:30:56 -0700 Subject: [PATCH 02/18] zynqmp: ipi: Consolidate IRQ #defines The bit mapping in I(E|D|S)R are equal, consolidate the #defines. Signed-off-by: Soren Brinkmann Acked-by: Michal Simek --- plat/xilinx/zynqmp/pm_service/pm_ipi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c index ef2b4fe6b5..8975f42fc1 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c @@ -66,8 +66,7 @@ #define IPI_APU_ISR (IPI_BASEADDR + 0X00000010) #define IPI_APU_IER (IPI_BASEADDR + 0X00000018) #define IPI_APU_IDR (IPI_BASEADDR + 0X0000001C) -#define IPI_APU_ISR_PMU_0_MASK 0X00010000 -#define IPI_APU_IER_PMU_0_MASK 0X00010000 +#define IPI_APU_IXR_PMU_0_MASK (1 << 16) #define IPI_TRIG_OFFSET 0 #define IPI_OBS_OFFSET 4 @@ -75,7 +74,7 @@ /* Power Management IPI interrupt number */ #define PM_INT_NUM 0 #define IPI_PMU_PM_INT_BASE (IPI_PMU_0_TRIG + (PM_INT_NUM * 0x1000)) -#define IPI_PMU_PM_INT_MASK (IPI_APU_ISR_PMU_0_MASK << PM_INT_NUM) +#define IPI_PMU_PM_INT_MASK (IPI_APU_IXR_PMU_0_MASK << PM_INT_NUM) #if (PM_INT_NUM < 0 || PM_INT_NUM > 3) #error PM_INT_NUM value out of range #endif From 1c87351bfd2a7cfd6bf87691426123c0dd7166c9 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 18 Apr 2016 10:46:19 -0700 Subject: [PATCH 03/18] context: Fix typo in comment Signed-off-by: Soren Brinkmann --- common/context_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/context_mgmt.c b/common/context_mgmt.c index 586d42a49e..3ccbd0301e 100644 --- a/common/context_mgmt.c +++ b/common/context_mgmt.c @@ -126,7 +126,7 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t /* * Set up SCTLR_ELx for the target exception level: - * EE bit is taken from the entrpoint attributes + * EE bit is taken from the entrypoint attributes * M, C and I bits must be zero (as required by PSCI specification) * * The target exception level is based on the spsr mode requested. From 01555332faa48a7361c2ff05446830ca791dd7b2 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 14 Apr 2016 10:27:00 -0700 Subject: [PATCH 04/18] zynqmp: Revise memory configuration options Drop the current configuration options for selecting the location of the ATF and TSP (ZYNQMP_ATF_LOCATION, ZYNQMP_TSP_RAM_LOCATION). The new configuration provides one default setup (ATF in OCM, BL32 in DRAM). Additionally, the new configuration options - ZYNQMP_ATF_MEM_BASE - ZYNQMP_ATF_MEM_SIZE - ZYNQMP_BL32_MEM_BASE - ZYNQMP_BL32_MEM_SIZE can be used to freely configure the memory locations used for ATF and secure payload. Also, allow setting the BL33 entry point via PRELOADED_BL33_BASE. Cc: petalinux-dev@xilinx.com Signed-off-by: Soren Brinkmann Acked-by: Alistair Francis --- docs/plat/xilinx-zynqmp.md | 12 ++--- plat/xilinx/zynqmp/include/platform_def.h | 66 +++++++++++------------ plat/xilinx/zynqmp/platform.mk | 38 +++++++------ plat/xilinx/zynqmp/zynqmp_def.h | 23 -------- 4 files changed, 52 insertions(+), 87 deletions(-) diff --git a/docs/plat/xilinx-zynqmp.md b/docs/plat/xilinx-zynqmp.md index 997d9a9a3a..166b4e3c88 100644 --- a/docs/plat/xilinx-zynqmp.md +++ b/docs/plat/xilinx-zynqmp.md @@ -21,14 +21,10 @@ make ERROR_DEPRECATED=1 RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zyn ``` # ZynqMP platform specific build options -* `ZYNQMP_ATF_LOCATION`: Specifies the location of the bl31 binary. Options: - - `tsram` : bl31 will be located in OCM (default) - - `tdram` : bl31 will be located in DRAM (address: 0x30000000) - -* `ZYNQMP_TSP_RAM_LOCATION`: Specifies the location of the bl32 binary and - secure payload dispatcher. Options: - - `tsram` : bl32/spd will be located in OCM (default) - - `tdram` : bl32/spd will be located in DRAM (address: 0x30000000) +* `ZYNQMP_ATF_MEM_BASE`: Specifies the base address of the bl31 binary. +* `ZYNQMP_ATF_MEM_SIZE`: Specifies the size of the memory region of the bl31 binary. +* `ZYNQMP_BL32_MEM_BASE`: Specifies the base address of the bl32 binary. +* `ZYNQMP_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary. # Power Domain Tree The following power domain tree represents the power domain model used by the diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h index 947a0f3bc8..c5ffac225b 100644 --- a/plat/xilinx/zynqmp/include/platform_def.h +++ b/plat/xilinx/zynqmp/include/platform_def.h @@ -50,56 +50,50 @@ /******************************************************************************* * BL31 specific defines. ******************************************************************************/ - -#define ZYNQMP_BL31_SIZE 0x1b000 /* * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if * present). BL31_BASE is calculated using the current BL31 debug size plus a * little space for growth. */ -#if ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM -# define BL31_BASE (ZYNQMP_TRUSTED_SRAM_LIMIT - \ - ZYNQMP_BL31_SIZE) -# define BL31_PROGBITS_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - 0x6000) -# define BL31_LIMIT ZYNQMP_TRUSTED_SRAM_LIMIT -#elif ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM -# define BL31_BASE (ZYNQMP_TRUSTED_DRAM_LIMIT - \ - ZYNQMP_BL31_SIZE) -# define BL31_PROGBITS_LIMIT (ZYNQMP_TRUSTED_DRAM_LIMIT - 0x6000) -# define BL31_LIMIT (ZYNQMP_TRUSTED_DRAM_BASE + \ - ZYNQMP_TRUSTED_DRAM_SIZE) +#ifndef ZYNQMP_ATF_MEM_BASE +# define BL31_BASE 0xfffe5000 +# define BL31_PROGBITS_LIMIT 0xffffa000 +# define BL31_LIMIT 0xffffffff #else -# error "Unsupported ZYNQMP_ATF_LOCATION_ID value" +# define BL31_BASE (ZYNQMP_ATF_MEM_BASE) +# define BL31_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_SIZE - 1) +# ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE +# define BL31_PROGBITS_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_PROGBITS_SIZE - 1) +# endif #endif /******************************************************************************* * BL32 specific defines. ******************************************************************************/ -/* - * On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM. - */ -#if ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM -# define TSP_SEC_MEM_BASE ZYNQMP_TRUSTED_SRAM_BASE -# define TSP_SEC_MEM_SIZE ZYNQMP_TRUSTED_SRAM_SIZE -# define TSP_PROGBITS_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - \ - ZYNQMP_BL31_SIZE) -# define BL32_BASE ZYNQMP_TRUSTED_SRAM_BASE -# define BL32_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - \ - ZYNQMP_BL31_SIZE) -#elif ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM -# define TSP_SEC_MEM_BASE ZYNQMP_TRUSTED_DRAM_BASE -# define TSP_SEC_MEM_SIZE (ZYNQMP_TRUSTED_DRAM_LIMIT - \ - ZYNQMP_BL31_SIZE) -# define BL32_BASE ZYNQMP_TRUSTED_DRAM_BASE -# define BL32_LIMIT (ZYNQMP_TRUSTED_DRAM_LIMIT - \ - ZYNQMP_BL31_SIZE) +#ifndef ZYNQMP_BL32_MEM_BASE +# define BL32_BASE 0x60000000 +# define BL32_LIMIT 0x7fffffff #else -# error "Unsupported ZYNQMP_TSP_RAM_LOCATION_ID value" +# define BL32_BASE (ZYNQMP_BL32_MEM_BASE) +# define BL32_LIMIT (ZYNQMP_BL32_MEM_BASE + ZYNQMP_BL32_MEM_SIZE - 1) #endif -/* - * ID of the secure physical generic timer interrupt used by the TSP. - */ +/******************************************************************************* + * BL33 specific defines. + ******************************************************************************/ +#ifndef PRELOADED_BL33_BASE +# define PLAT_ARM_NS_IMAGE_OFFSET 0x8000000 +#else +# define PLAT_ARM_NS_IMAGE_OFFSET PRELOADED_BL33_BASE +#endif + +/******************************************************************************* + * TSP specific defines. + ******************************************************************************/ +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1) + +/* ID of the secure physical generic timer interrupt used by the TSP */ #define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER /******************************************************************************* diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index febff29f49..e0a325d0d2 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -31,29 +31,27 @@ PROGRAMMABLE_RESET_ADDRESS := 1 PSCI_EXTENDED_STATE_ID := 1 A53_DISABLE_NON_TEMPORAL_HINT := 0 -ZYNQMP_ATF_LOCATION ?= tsram -ifeq (${ZYNQMP_ATF_LOCATION}, tsram) - ZYNQMP_ATF_LOCATION_ID := ZYNQMP_IN_TRUSTED_SRAM -else ifeq (${ZYNQMP_ATF_LOCATION}, tdram) - ZYNQMP_ATF_LOCATION_ID := ZYNQMP_IN_TRUSTED_DRAM -else - $(error "Unsupported ZYNQMP_ATF_LOCATION value") +ifdef ZYNQMP_ATF_MEM_BASE + $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE)) + + ifndef ZYNQMP_ATF_MEM_SIZE + $(error "ZYNQMP_ATF_BASE defined without ZYNQMP_ATF_SIZE") + endif + $(eval $(call add_define,ZYNQMP_ATF_MEM_SIZE)) + + ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE + $(eval $(call add_define,ZYNQMP_ATF_MEM_PROGBITS_SIZE)) + endif endif -# On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM. -# Trusted SRAM is the default. -ZYNQMP_TSP_RAM_LOCATION ?= tsram -ifeq (${ZYNQMP_TSP_RAM_LOCATION}, tsram) - ZYNQMP_TSP_RAM_LOCATION_ID := ZYNQMP_IN_TRUSTED_SRAM -else ifeq (${ZYNQMP_TSP_RAM_LOCATION}, tdram) - ZYNQMP_TSP_RAM_LOCATION_ID := ZYNQMP_IN_TRUSTED_DRAM -else - $(error "Unsupported ZYNQMP_TSP_RAM_LOCATION value") -endif +ifdef ZYNQMP_BL32_MEM_BASE + $(eval $(call add_define,ZYNQMP_BL32_MEM_BASE)) -# Process flags -$(eval $(call add_define,ZYNQMP_ATF_LOCATION_ID)) -$(eval $(call add_define,ZYNQMP_TSP_RAM_LOCATION_ID)) + ifndef ZYNQMP_BL32_MEM_SIZE + $(error "ZYNQMP_BL32_BASE defined without ZYNQMP_BL32_SIZE") + endif + $(eval $(call add_define,ZYNQMP_BL32_MEM_SIZE)) +endif PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ -Iinclude/plat/arm/common/aarch64/ \ diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 32190e41f9..504517dbf3 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -43,19 +43,6 @@ /******************************************************************************* * ZYNQMP memory map related constants ******************************************************************************/ - -#define ZYNQMP_TRUSTED_SRAM_BASE 0xFFFC0000 -#define ZYNQMP_TRUSTED_SRAM_SIZE 0x00040000 -#define ZYNQMP_TRUSTED_SRAM_LIMIT (ZYNQMP_TRUSTED_SRAM_BASE + \ - ZYNQMP_TRUSTED_SRAM_SIZE) - - -/* Location of trusted dram on the base zynqmp */ -#define ZYNQMP_TRUSTED_DRAM_BASE 0x30000000 /* Can't overlap TZROM area */ -#define ZYNQMP_TRUSTED_DRAM_SIZE 0x10000000 -#define ZYNQMP_TRUSTED_DRAM_LIMIT (ZYNQMP_TRUSTED_DRAM_BASE + \ - ZYNQMP_TRUSTED_DRAM_SIZE) - /* Aggregate of all devices in the first GB */ #define DEVICE0_BASE 0xFF000000 #define DEVICE0_SIZE 0x00E00000 @@ -114,16 +101,6 @@ #define PMU_GLOBAL_CNTRL_FW_IS_PRESENT (1 << 4) -#define DRAM1_BASE 0x00000000ull -#define DRAM1_SIZE 0x10000000ull -#define DRAM1_END (DRAM1_BASE + DRAM1_SIZE - 1) - -#define DRAM_BASE DRAM1_BASE -#define DRAM_SIZE DRAM1_SIZE - -/* Load address of BL33 in the ZYNQMP port */ -#define PLAT_ARM_NS_IMAGE_OFFSET (DRAM1_BASE + 0x8000000) /* DRAM + 128MB */ - /******************************************************************************* * CCI-400 related constants ******************************************************************************/ From e543e79b2d523fea98fe519518246911eec834aa Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 18 Apr 2016 11:27:48 -0700 Subject: [PATCH 05/18] zynqmp: Remove bogus comment Signed-off-by: Soren Brinkmann Acked-by: Michal Simek --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index 429eec27e4..87e47a5f9f 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -271,13 +271,6 @@ int zynqmp_is_pmu_up(void) return zynqmp_pmufw_present; } -/* - * A single boot loader stack is expected to work on both the Foundation ZYNQMP - * models and the two flavours of the Base ZYNQMP models (AEMv8 & Cortex). The - * SYS_ID register provides a mechanism for detecting the differences between - * these platforms. This information is stored in a per-BL array to allow the - * code to take the correct path.Per BL platform configuration. - */ void zynqmp_config_setup(void) { zynqmp_discover_pmufw(); From 2cb5bac9849b596eed0107be1c07dc4316ce6ee6 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 18 Apr 2016 11:49:42 -0700 Subject: [PATCH 06/18] zynqmp: Introduce zynqmp_get_bootmode Provide a function to retrieve the bootmode. Signed-off-by: Soren Brinkmann Acked-by: Michal Simek --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 7 +++++++ plat/xilinx/zynqmp/zynqmp_def.h | 4 ++++ plat/xilinx/zynqmp/zynqmp_private.h | 1 + 3 files changed, 12 insertions(+) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index 87e47a5f9f..21d62570f3 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -271,6 +271,13 @@ int zynqmp_is_pmu_up(void) return zynqmp_pmufw_present; } +unsigned int zynqmp_get_bootmode(void) +{ + uint32_t r = mmio_read_32(CRL_APB_BOOT_MODE_USER); + + return r & CRL_APB_BOOT_MODE_MASK; +} + void zynqmp_config_setup(void) { zynqmp_discover_pmufw(); diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 504517dbf3..9496ec4999 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -63,6 +63,7 @@ #define CRL_APB_BASE 0xFF5E0000 #define CRL_APB_RPLL_CTRL (CRL_APB_BASE + 0x30) #define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_BASE + 0x128) +#define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200) #define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218) #define CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1 << 24) @@ -71,6 +72,9 @@ #define CRL_APB_RESET_CTRL_SOFT_RESET (1 << 4) +#define CRL_APB_BOOT_MODE_MASK (0xf << 0) +#define ZYNQMP_BOOTMODE_JTAG 0 + /* system counter registers and bitfields */ #define IOU_SCNTRS_BASE 0xFF260000 #define IOU_SCNTRS_CONTROL (IOU_SCNTRS_BASE + 0) diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h index 1f5be39ba4..228d8dce46 100644 --- a/plat/xilinx/zynqmp/zynqmp_private.h +++ b/plat/xilinx/zynqmp/zynqmp_private.h @@ -38,5 +38,6 @@ void zynqmp_config_setup(void); /* ZynqMP specific functions */ unsigned int zynqmp_get_uart_clk(void); int zynqmp_is_pmu_up(void); +unsigned int zynqmp_get_bootmode(void); #endif /* __ZYNQMP_PRIVATE_H__ */ From b96f77c65ba5ce91091044b43704562e622a353b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 15 Jun 2015 14:22:50 +0200 Subject: [PATCH 07/18] zynqmp: FSBL->ATF handover Parse the parameter structure the FSBL populates, to populate the bl32 and bl33 image structures. Cc: Sarat Chand Savitala Cc: petalinux-dev@xilinx.com Signed-off-by: Michal Simek [ SB - pass pointers to structs instead of structs - handle execution state parameter - populate bl32 SPSR - add documentation - query bootmode and consider missing handoff parameters an error when not in JTAG boot mode ] Signed-off-by: Soren Brinkmann --- docs/plat/xilinx-zynqmp.md | 7 + plat/xilinx/zynqmp/bl31_zynqmp_setup.c | 28 +-- plat/xilinx/zynqmp/plat_startup.c | 288 +++++++++++++++++++++++++ plat/xilinx/zynqmp/platform.mk | 1 + plat/xilinx/zynqmp/zynqmp_def.h | 1 + plat/xilinx/zynqmp/zynqmp_private.h | 4 + 6 files changed, 315 insertions(+), 14 deletions(-) create mode 100644 plat/xilinx/zynqmp/plat_startup.c diff --git a/docs/plat/xilinx-zynqmp.md b/docs/plat/xilinx-zynqmp.md index 166b4e3c88..2af841b1f9 100644 --- a/docs/plat/xilinx-zynqmp.md +++ b/docs/plat/xilinx-zynqmp.md @@ -26,6 +26,13 @@ make ERROR_DEPRECATED=1 RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zyn * `ZYNQMP_BL32_MEM_BASE`: Specifies the base address of the bl32 binary. * `ZYNQMP_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary. +# FSBL->ATF Parameter Passing +The FSBL populates a data structure with image information for the ATF. The ATF +uses that data to hand off to the loaded images. The address of the handoff data +structure is passed in the ```PMU_GLOBAL.GLOBAL_GEN_STORAGE6``` register. The +register is free to be used by other software once the ATF is bringing up +further firmware images. + # Power Domain Tree The following power domain tree represents the power domain model used by the ATF for ZynqMP: diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c index 9c9d18d14c..7b8c567005 100644 --- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -113,25 +113,25 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, * present. */ - /* Populate entry point information for BL32 and BL33 */ + /* Populate common information for BL32 and BL33 */ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); - bl32_image_ep_info.pc = BL32_BASE; - bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); - - NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); - SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); - - /* - * Tell BL31 where the non-trusted software image - * is located and the entry state information - */ - bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); - bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, - DISABLE_ALL_EXCEPTIONS); SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + if (zynqmp_get_bootmode() == ZYNQMP_BOOTMODE_JTAG) { + /* use build time defaults in JTAG boot mode */ + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + /* use parameters from FSBL */ + fsbl_atf_handover(&bl32_image_ep_info, &bl33_image_ep_info); + } + + NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); } diff --git a/plat/xilinx/zynqmp/plat_startup.c b/plat/xilinx/zynqmp/plat_startup.c new file mode 100644 index 0000000000..59e49fab84 --- /dev/null +++ b/plat/xilinx/zynqmp/plat_startup.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "zynqmp_def.h" + +/* + * ATFHandoffParams + * Parameter bitfield encoding + * ----------------------------------------------------------------------------- + * Exec State 0 0 -> Aarch64, 1-> Aarch32 + * endianess 1 0 -> LE, 1 -> BE + * secure (TZ) 2 0 -> Non secure, 1 -> secure + * EL 3:4 00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3 + * CPU# 5:6 00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3 + */ + +#define FSBL_FLAGS_ESTATE_SHIFT 0 +#define FSBL_FLAGS_ESTATE_MASK (1 << FSBL_FLAGS_ESTATE_SHIFT) +#define FSBL_FLAGS_ESTATE_A64 0 +#define FSBL_FLAGS_ESTATE_A32 1 + +#define FSBL_FLAGS_ENDIAN_SHIFT 1 +#define FSBL_FLAGS_ENDIAN_MASK (1 << FSBL_FLAGS_ENDIAN_SHIFT) +#define FSBL_FLAGS_ENDIAN_LE 0 +#define FSBL_FLAGS_ENDIAN_BE 1 + +#define FSBL_FLAGS_TZ_SHIFT 2 +#define FSBL_FLAGS_TZ_MASK (1 << FSBL_FLAGS_TZ_SHIFT) +#define FSBL_FLAGS_NON_SECURE 0 +#define FSBL_FLAGS_SECURE 1 + +#define FSBL_FLAGS_EL_SHIFT 3 +#define FSBL_FLAGS_EL_MASK (3 << FSBL_FLAGS_EL_SHIFT) +#define FSBL_FLAGS_EL0 0 +#define FSBL_FLAGS_EL1 1 +#define FSBL_FLAGS_EL2 2 +#define FSBL_FLAGS_EL3 3 + +#define FSBL_FLAGS_CPU_SHIFT 5 +#define FSBL_FLAGS_CPU_MASK (3 << FSBL_FLAGS_CPU_SHIFT) +#define FSBL_FLAGS_A53_0 0 +#define FSBL_FLAGS_A53_1 1 +#define FSBL_FLAGS_A53_2 2 +#define FSBL_FLAGS_A53_3 3 + +#define FSBL_MAX_PARTITIONS 8 + +/* Structure corresponding to each partition entry */ +struct xfsbl_partition { + uint64_t entry_point; + uint64_t flags; +}; + +/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */ +struct xfsbl_atf_handoff_params { + uint8_t magic[4]; + uint32_t num_entries; + struct xfsbl_partition partition[FSBL_MAX_PARTITIONS]; +}; + +/** + * @partition: Pointer to partition struct + * + * Get the target CPU for @partition. + * + * Return: FSBL_FLAGS_A53_0, FSBL_FLAGS_A53_1, FSBL_FLAGS_A53_2 or FSBL_FLAGS_A53_3 + */ +static int get_fsbl_cpu(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_CPU_MASK; + + return flags >> FSBL_FLAGS_CPU_SHIFT; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target exception level for @partition. + * + * Return: FSBL_FLAGS_EL0, FSBL_FLAGS_EL1, FSBL_FLAGS_EL2 or FSBL_FLAGS_EL3 + */ +static int get_fsbl_el(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_EL_MASK; + + return flags >> FSBL_FLAGS_EL_SHIFT;; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target security state for @partition. + * + * Return: FSBL_FLAGS_NON_SECURE or FSBL_FLAGS_SECURE + */ +static int get_fsbl_ss(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_TZ_MASK; + + return flags >> FSBL_FLAGS_TZ_SHIFT; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target endianess for @partition. + * + * Return: SPSR_E_LITTLE or SPSR_E_BIG + */ +static int get_fsbl_endian(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_ENDIAN_MASK; + + flags >>= FSBL_FLAGS_ENDIAN_SHIFT; + + if (flags == FSBL_FLAGS_ENDIAN_BE) + return SPSR_E_BIG; + else + return SPSR_E_LITTLE; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target execution state for @partition. + * + * Return: FSBL_FLAGS_ESTATE_A32 or FSBL_FLAGS_ESTATE_A64 + */ +static int get_fsbl_estate(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_ESTATE_MASK; + + return flags >> FSBL_FLAGS_ESTATE_SHIFT; +} + +/** + * Populates the bl32 and bl33 image info structures + * @bl32: BL32 image info structure + * @bl33: BL33 image info structure + * + * Process the handoff paramters from the FSBL and populate the BL32 and BL33 + * image info structures accordingly. + */ +void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33) +{ + uint64_t atf_handoff_addr; + const struct xfsbl_atf_handoff_params *ATFHandoffParams; + + atf_handoff_addr = mmio_read_32(PMU_GLOBAL_GEN_STORAGE6); + assert((atf_handoff_addr < BL31_BASE) || + (atf_handoff_addr > (uint64_t)&__BL31_END__)); + if (!atf_handoff_addr) { + ERROR("BL31: No ATF handoff structure passed\n"); + panic(); + } + + ATFHandoffParams = (struct xfsbl_atf_handoff_params *)atf_handoff_addr; + if ((ATFHandoffParams->magic[0] != 'X') || + (ATFHandoffParams->magic[1] != 'L') || + (ATFHandoffParams->magic[2] != 'N') || + (ATFHandoffParams->magic[3] != 'X')) { + ERROR("BL31: invalid ATF handoff structure at %lx\n", + atf_handoff_addr); + panic(); + } + + VERBOSE("BL31: ATF handoff params at:0x%lx, entries:%u\n", + atf_handoff_addr, ATFHandoffParams->num_entries); + if (ATFHandoffParams->num_entries > FSBL_MAX_PARTITIONS) { + ERROR("BL31: ATF handoff params: too many partitions (%u/%u)\n", + ATFHandoffParams->num_entries, FSBL_MAX_PARTITIONS); + panic(); + } + + /* + * we loop over all passed entries but only populate two image structs + * (bl32, bl33). I.e. the last applicable images in the handoff + * structure will be used for the hand off + */ + for (size_t i = 0; i < ATFHandoffParams->num_entries; i++) { + entry_point_info_t *image; + int target_estate, target_secure; + int target_cpu, target_endianess, target_el; + + VERBOSE("BL31: %zd: entry:0x%lx, flags:0x%lx\n", i, + ATFHandoffParams->partition[i].entry_point, + ATFHandoffParams->partition[i].flags); + + target_cpu = get_fsbl_cpu(&ATFHandoffParams->partition[i]); + if (target_cpu != FSBL_FLAGS_A53_0) { + WARN("BL31: invalid target CPU (%i)\n", target_cpu); + continue; + } + + target_el = get_fsbl_el(&ATFHandoffParams->partition[i]); + if ((target_el == FSBL_FLAGS_EL3) || + (target_el == FSBL_FLAGS_EL0)) { + WARN("BL31: invalid exception level (%i)\n", target_el); + continue; + } + + target_secure = get_fsbl_ss(&ATFHandoffParams->partition[i]); + if (target_secure == FSBL_FLAGS_SECURE && + target_el == FSBL_FLAGS_EL2) { + WARN("BL31: invalid security state (%i) for exception level (%i)\n", + target_secure, target_el); + continue; + } + + target_estate = get_fsbl_estate(&ATFHandoffParams->partition[i]); + target_endianess = get_fsbl_endian(&ATFHandoffParams->partition[i]); + + if (target_secure == FSBL_FLAGS_SECURE) { + image = bl32; + + if (target_estate == FSBL_FLAGS_ESTATE_A32) + bl32->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + target_endianess, + DISABLE_ALL_EXCEPTIONS); + else + bl32->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + image = bl33; + + if (target_estate == FSBL_FLAGS_ESTATE_A32) { + if (target_el == FSBL_FLAGS_EL2) + target_el = MODE32_hyp; + else + target_el = MODE32_sys; + + bl33->spsr = SPSR_MODE32(target_el, SPSR_T_ARM, + target_endianess, + DISABLE_ALL_EXCEPTIONS); + } else { + if (target_el == FSBL_FLAGS_EL2) + target_el = MODE_EL2; + else + target_el = MODE_EL1; + + bl33->spsr = SPSR_64(target_el, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + } + + VERBOSE("Setting up %s entry point to:%lx, el:%x\n", + target_secure == FSBL_FLAGS_SECURE ? "BL32" : "BL33", + ATFHandoffParams->partition[i].entry_point, + target_el); + image->pc = ATFHandoffParams->partition[i].entry_point; + + if (target_endianess == SPSR_E_BIG) + EP_SET_EE(image->h.attr, EP_EE_BIG); + else + EP_SET_EE(image->h.attr, EP_EE_LITTLE); + } +} diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index e0a325d0d2..abbb15a551 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -82,6 +82,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ plat/xilinx/zynqmp/bl31_zynqmp_setup.c \ plat/xilinx/zynqmp/plat_psci.c \ plat/xilinx/zynqmp/plat_zynqmp.c \ + plat/xilinx/zynqmp/plat_startup.c \ plat/xilinx/zynqmp/plat_topology.c \ plat/xilinx/zynqmp/sip_svc_setup.c \ plat/xilinx/zynqmp/pm_service/pm_svc_main.c \ diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 9496ec4999..13498b5c6f 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -98,6 +98,7 @@ /* PMU registers and bitfields */ #define PMU_GLOBAL_BASE 0xFFD80000 #define PMU_GLOBAL_CNTRL (PMU_GLOBAL_BASE + 0) +#define PMU_GLOBAL_GEN_STORAGE6 (PMU_GLOBAL_BASE + 0x48) #define PMU_GLOBAL_REQ_PWRUP_STATUS (PMU_GLOBAL_BASE + 0x110) #define PMU_GLOBAL_REQ_PWRUP_EN (PMU_GLOBAL_BASE + 0x118) #define PMU_GLOBAL_REQ_PWRUP_DIS (PMU_GLOBAL_BASE + 0x11c) diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h index 228d8dce46..ddef37b8f3 100644 --- a/plat/xilinx/zynqmp/zynqmp_private.h +++ b/plat/xilinx/zynqmp/zynqmp_private.h @@ -40,4 +40,8 @@ unsigned int zynqmp_get_uart_clk(void); int zynqmp_is_pmu_up(void); unsigned int zynqmp_get_bootmode(void); +/* For FSBL handover */ +void fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info, + entry_point_info_t *bl33_image_ep_info); + #endif /* __ZYNQMP_PRIVATE_H__ */ From 142ec0433ff3c3fc5e8ba5af71b94cc2d44c1ad6 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 22 Apr 2016 10:02:46 -0700 Subject: [PATCH 08/18] zynqmp: Reduce mapped memory area The GIC area is specified larger than it needs to be and can be reduced. Which allows reducing the structures required for the translation tables as well. This results in a reduction of memory footprint of ca. 4k. Signed-off-by: Soren Brinkmann Acked-by: Michal Simek --- plat/xilinx/zynqmp/include/platform_def.h | 8 ++++++-- plat/xilinx/zynqmp/zynqmp_def.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h index c5ffac225b..76a52de889 100644 --- a/plat/xilinx/zynqmp/include/platform_def.h +++ b/plat/xilinx/zynqmp/include/platform_def.h @@ -100,8 +100,12 @@ * Platform specific page table and MMU setup constants ******************************************************************************/ #define ADDR_SPACE_SIZE (1ull << 32) -#define MAX_XLAT_TABLES 5 -#define MAX_MMAP_REGIONS 7 +#define MAX_MMAP_REGIONS 6 +#if IMAGE_BL32 +# define MAX_XLAT_TABLES 5 +#else +# define MAX_XLAT_TABLES 4 +#endif #define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 13498b5c6f..4ff1f468ca 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -47,7 +47,7 @@ #define DEVICE0_BASE 0xFF000000 #define DEVICE0_SIZE 0x00E00000 #define DEVICE1_BASE 0xF9000000 -#define DEVICE1_SIZE 0x01000000 +#define DEVICE1_SIZE 0x00800000 /* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ #define CRF_APB_BASE 0xFD1A0000 From df4c59c5d2c0ef198f6d36885e3a56800334f233 Mon Sep 17 00:00:00 2001 From: Filip Drazic Date: Thu, 12 May 2016 16:17:31 +0200 Subject: [PATCH 09/18] zynqmp: pm: Removed double declaration of pm_ipi_send functions Functions pm_ipi_send and pm_ipi_send_sync are declared in pm_ipi.h Signed-off-by: Filip Drazic Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 1 + plat/xilinx/zynqmp/pm_service/pm_client.h | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 2f2e2edfe6..053281ee07 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -36,6 +36,7 @@ #include #include #include "pm_client.h" +#include "pm_ipi.h" #include "pm_common.h" #include "pm_api_sys.h" diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.h b/plat/xilinx/zynqmp/pm_service/pm_client.h index b9f196d773..9483b0d1b8 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.h +++ b/plat/xilinx/zynqmp/pm_service/pm_client.h @@ -40,11 +40,6 @@ #include "pm_common.h" /* Functions to be implemented by each PU */ -enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, - uint32_t payload[PAYLOAD_ARG_CNT]); -enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, - uint32_t payload[PAYLOAD_ARG_CNT], - uint32_t *val); void pm_client_suspend(const struct pm_proc *proc); void pm_client_abort_suspend(void); void pm_client_wakeup(const struct pm_proc *proc); From 493541d640aee7e5d35a80534a7e51c09f09e7e4 Mon Sep 17 00:00:00 2001 From: Anes Hadziahmetagic Date: Thu, 12 May 2016 16:17:30 +0200 Subject: [PATCH 10/18] zynqmp: pm: Implemented 'get_op_characteristic' PM API call Signed-off-by: Anes Hadziahmetagic Signed-off-by: Filip Drazic Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 20 ++++++++++++++------ plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 3 ++- plat/xilinx/zynqmp/pm_service/pm_defs.h | 2 +- plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 8 ++++++-- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 053281ee07..5af0163eec 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -395,17 +395,25 @@ enum pm_ret_status pm_register_notifier(enum pm_node_id nid, } /** - * pm_get_op_characteristic() - PM call to get a particular operating - * characteristic of a node - * @nid Node ID - * @type Operating characterstic type to be returned + * pm_get_op_characteristic() - PM call to request operating characteristics + * of a node + * @nid Node id of the slave + * @type Type of the operating characteristic + * (power, temperature and latency) + * @result Returns the operating characteristic for the requested node, + * specified by the type * * @return Returns status, either success or error+reason */ enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, - enum pm_opchar_type type) + enum pm_opchar_type type, + uint32_t *result) { - return PM_RET_ERROR_NOTSUPPORTED; + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type); + return pm_ipi_send_sync(primary_proc, payload, result); } /* Direct-Control API functions */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index f0365cd997..22bdb4774f 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -91,7 +91,8 @@ enum pm_ret_status pm_register_notifier(enum pm_node_id nid, unsigned int wake, unsigned int enable); enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, - enum pm_opchar_type type); + enum pm_opchar_type type, + uint32_t *result); enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid, enum pm_ret_status status, unsigned int oppoint); diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 08f4aab799..2fd05fe900 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -171,8 +171,8 @@ enum pm_ram_state { enum pm_opchar_type { PM_OPCHAR_TYPE_POWER = 1, - PM_OPCHAR_TYPE_ENERGY, PM_OPCHAR_TYPE_TEMP, + PM_OPCHAR_TYPE_LATENCY, }; /** diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index 67440650bb..e3c25c31cc 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -191,8 +191,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); case PM_GET_OP_CHARACTERISTIC: - ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1]); - SMC_RET1(handle, (uint64_t)ret); + { + 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)); + } case PM_REGISTER_NOTIFIER: ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], From fc65b87b8a1477f18c18646f84b3dfda0573d126 Mon Sep 17 00:00:00 2001 From: Anes Hadziahmetagic Date: Thu, 12 May 2016 16:17:34 +0200 Subject: [PATCH 11/18] zynqmp: pm: Implement pm_register_notifier PM API function Signed-off-by: Anes Hadziahmetagic Signed-off-by: Filip Drazic Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 5af0163eec..eac7801b05 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -391,7 +391,12 @@ enum pm_ret_status pm_register_notifier(enum pm_node_id nid, unsigned int wake, unsigned int enable) { - return PM_RET_ERROR_NOTSUPPORTED; + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD5(payload, PM_REGISTER_NOTIFIER, + nid, event, wake, enable); + + return pm_ipi_send(primary_proc, payload); } /** From 8212f1f0ee9e99eaf2610d263f251380996bf9f3 Mon Sep 17 00:00:00 2001 From: Stefan Krsmanovic Date: Fri, 20 May 2016 15:51:08 +0200 Subject: [PATCH 12/18] zynqmp: Put pm_secure_lock in coherent memory region DEFINE_BAKERY_LOCK() macro is used to put lock in coherent memory region. ARM Trusted Firmware design guide, chapter 11 states that bakery_lock data structures should be allocated in coherent memory region because it is accessed by multiple CPUs with mismatched shareability, cacheability and memory attributes. Signed-off-by: Stefan Krsmanovic Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_ipi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c index 8975f42fc1..c3e7ccb505 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c @@ -81,7 +81,7 @@ #define IPI_APU_MASK 1U -static bakery_lock_t pm_secure_lock; +DEFINE_BAKERY_LOCK(pm_secure_lock); const struct pm_ipi apu_ipi = { .mask = IPI_APU_MASK, From 03b8077309d9c55118737426c1e1e4bd99c7ae60 Mon Sep 17 00:00:00 2001 From: Stefan Krsmanovic Date: Fri, 20 May 2016 15:51:09 +0200 Subject: [PATCH 13/18] zynqmp: Add bakery_lock to protect APU_PWRCTRL register access Access to APU_PWRCTRL register is protected during suspend/wakeup pocedure in order to save valid state. If more than one CPU is accessing this register it can be left in corrupted state during read-modify-write process. Signed-off-by: Stefan Krsmanovic Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_client.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c index eb986bca40..d3396dfa9c 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.c +++ b/plat/xilinx/zynqmp/pm_service/pm_client.c @@ -33,6 +33,7 @@ * for getting information about and changing state of the APU. */ +#include #include #include #include @@ -47,6 +48,7 @@ #define OCM_BANK_3 (OCM_BANK_2 + 0x10000) #define UNDEFINED_CPUID (~0) +DEFINE_BAKERY_LOCK(pm_client_secure_lock); /* Declaration of linker defined symbol */ extern unsigned long __BL31_END__; @@ -162,8 +164,12 @@ const struct pm_proc *primary_proc = &pm_procs_all[0]; */ void pm_client_suspend(const struct pm_proc *proc) { + bakery_lock_get(&pm_client_secure_lock); + /* Set powerdown request */ mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); } @@ -177,9 +183,14 @@ void pm_client_abort_suspend(void) { /* Enable interrupts at processor level (for current cpu) */ gicv2_cpuif_enable(); + + bakery_lock_get(&pm_client_secure_lock); + /* Clear powerdown request */ mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); } /** @@ -195,8 +206,12 @@ void pm_client_wakeup(const struct pm_proc *proc) if (cpuid == UNDEFINED_CPUID) return; + bakery_lock_get(&pm_client_secure_lock); + /* clear powerdown bit for affected cpu */ uint32_t val = mmio_read_32(APU_PWRCTL); val &= ~(proc->pwrdn_mask); mmio_write_32(APU_PWRCTL, val); + + bakery_lock_release(&pm_client_secure_lock); } From 648fe99e9f9058368c8cdbbe128929591fd87fc7 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 20 May 2016 07:05:00 -0700 Subject: [PATCH 14/18] zynqmp: Ignore the revision field of the IDCODE The revision field may change between silicon revisions without changing the mapping to a part. This avoids errors like: ERROR: Incorrect XILINX IDCODE 0x14738093, maskid 0x4600093 NOTICE: ATF running on XCZUUNKN/EP108 v3/RTL5.1 at 0xfffe5000 on parts with a newer revision. Reported-by: Love Kumar Signed-off-by: Soren Brinkmann Acked-by: Alistair Francis Tested-by: Love Kumar --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index 21d62570f3..aefc827cca 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -183,11 +183,9 @@ static char *zynqmp_print_silicon_idcode(void) tmp = id; tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | - ZYNQMP_CSU_IDCODE_FAMILY_MASK | - ZYNQMP_CSU_IDCODE_REVISION_MASK; + ZYNQMP_CSU_IDCODE_FAMILY_MASK; maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | - ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT | - ZYNQMP_CSU_IDCODE_REVISION << ZYNQMP_CSU_IDCODE_REVISION_SHIFT; + ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; if (tmp != maskid) { ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); return "UNKN"; From e3f0391e855bd8a8cdfa25985caed7ef2b8666a7 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 19 May 2016 07:20:14 -0700 Subject: [PATCH 15/18] zynqmp: PSCI: Wait for FW completing wake requests Powering up cores didn't wait for the PMUFW to complete the request, which could result in cores failing to power up in Linux. Reported-by: Koteswararao Nayudu Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/plat_psci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c index d693a2dbf8..56eb742aca 100644 --- a/plat/xilinx/zynqmp/plat_psci.c +++ b/plat/xilinx/zynqmp/plat_psci.c @@ -104,7 +104,7 @@ static int zynqmp_pwr_domain_on(u_register_t mpidr) proc = pm_get_proc(cpu_id); /* Send request to PMU to wake up selected APU CPU core */ - pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_NO); + pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_BLOCKING); return PSCI_E_SUCCESS; } From 55eae0d4ff49debef02f24d742977175b60734c0 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sun, 29 May 2016 09:48:26 -0700 Subject: [PATCH 16/18] zynqmp: Fix spelling of endianness Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/plat_startup.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plat/xilinx/zynqmp/plat_startup.c b/plat/xilinx/zynqmp/plat_startup.c index 59e49fab84..a5de62412c 100644 --- a/plat/xilinx/zynqmp/plat_startup.c +++ b/plat/xilinx/zynqmp/plat_startup.c @@ -39,7 +39,7 @@ * Parameter bitfield encoding * ----------------------------------------------------------------------------- * Exec State 0 0 -> Aarch64, 1-> Aarch32 - * endianess 1 0 -> LE, 1 -> BE + * endianness 1 0 -> LE, 1 -> BE * secure (TZ) 2 0 -> Non secure, 1 -> secure * EL 3:4 00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3 * CPU# 5:6 00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3 @@ -134,7 +134,7 @@ static int get_fsbl_ss(const struct xfsbl_partition *partition) /** * @partition: Pointer to partition struct * - * Get the target endianess for @partition. + * Get the target endianness for @partition. * * Return: SPSR_E_LITTLE or SPSR_E_BIG */ @@ -211,7 +211,7 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33) for (size_t i = 0; i < ATFHandoffParams->num_entries; i++) { entry_point_info_t *image; int target_estate, target_secure; - int target_cpu, target_endianess, target_el; + int target_cpu, target_endianness, target_el; VERBOSE("BL31: %zd: entry:0x%lx, flags:0x%lx\n", i, ATFHandoffParams->partition[i].entry_point, @@ -239,14 +239,14 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33) } target_estate = get_fsbl_estate(&ATFHandoffParams->partition[i]); - target_endianess = get_fsbl_endian(&ATFHandoffParams->partition[i]); + target_endianness = get_fsbl_endian(&ATFHandoffParams->partition[i]); if (target_secure == FSBL_FLAGS_SECURE) { image = bl32; if (target_estate == FSBL_FLAGS_ESTATE_A32) bl32->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, - target_endianess, + target_endianness, DISABLE_ALL_EXCEPTIONS); else bl32->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, @@ -261,7 +261,7 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33) target_el = MODE32_sys; bl33->spsr = SPSR_MODE32(target_el, SPSR_T_ARM, - target_endianess, + target_endianness, DISABLE_ALL_EXCEPTIONS); } else { if (target_el == FSBL_FLAGS_EL2) @@ -280,7 +280,7 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33) target_el); image->pc = ATFHandoffParams->partition[i].entry_point; - if (target_endianess == SPSR_E_BIG) + if (target_endianness == SPSR_E_BIG) EP_SET_EE(image->h.attr, EP_EE_BIG); else EP_SET_EE(image->h.attr, EP_EE_LITTLE); From a29f50c943039c23e1ad3fcb6d9539f5d29ccc49 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sun, 29 May 2016 09:48:44 -0700 Subject: [PATCH 17/18] zynqmp: Remove double ';' Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/plat_startup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/xilinx/zynqmp/plat_startup.c b/plat/xilinx/zynqmp/plat_startup.c index a5de62412c..c2c9bfb058 100644 --- a/plat/xilinx/zynqmp/plat_startup.c +++ b/plat/xilinx/zynqmp/plat_startup.c @@ -114,7 +114,7 @@ static int get_fsbl_el(const struct xfsbl_partition *partition) { uint64_t flags = partition->flags & FSBL_FLAGS_EL_MASK; - return flags >> FSBL_FLAGS_EL_SHIFT;; + return flags >> FSBL_FLAGS_EL_SHIFT; } /** From 2ba6895919546c5b346e49b1390e64b76100e85c Mon Sep 17 00:00:00 2001 From: Mirela Simonovic Date: Tue, 7 Jun 2016 18:15:40 +0200 Subject: [PATCH 18/18] zynqmp: pm: Added NODE_IPI_APU slave node ID in pm_defs.h NODE_IPI_APU is the node ID of APU's IPI device. If APU should be woken-up on an IPI from FPD power down, this node shall be set as the wake-up source upon suspend. Signed-off-by: Mirela Simonovic --- plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 2fd05fe900..adeec64bed 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -142,6 +142,7 @@ enum pm_node_id { NODE_RPLL, NODE_IOPLL, NODE_DDR, + NODE_IPI_APU, }; enum pm_request_ack {