Merge "corstone700: splitting the platform support into FVP and FPGA" into integration
diff --git a/docs/perf/psci-performance-juno.rst b/docs/perf/psci-performance-juno.rst
index c127c1c..eab3e4d 100644
--- a/docs/perf/psci-performance-juno.rst
+++ b/docs/perf/psci-performance-juno.rst
@@ -286,7 +286,7 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
 
-.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf
+.. _Juno R1 platform: https://static.docs.arm.com/100122/0100/arm_versatile_express_juno_r1_development_platform_(v2m_juno_r1)_technical_reference_manual_100122_0100_05_en.pdf
 .. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index a1e0659..d82380d 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -34,7 +34,7 @@
 
     make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
 
-.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
+.. _U-Boot documentation: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/sunxi/README.sunxi64
 
 Trusted OS dispatcher
 ---------------------
diff --git a/docs/plat/meson-axg.rst b/docs/plat/meson-axg.rst
index 1e4b2c2..6f6732e 100644
--- a/docs/plat/meson-axg.rst
+++ b/docs/plat/meson-axg.rst
@@ -24,4 +24,4 @@
 instructions in the `U-Boot repository`_, replacing the mentioned **bl31.img**
 by the one built from this port.
 
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/s400/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/s400.rst
diff --git a/docs/plat/meson-g12a.rst b/docs/plat/meson-g12a.rst
index 7cd1bf7..9588ec4 100644
--- a/docs/plat/meson-g12a.rst
+++ b/docs/plat/meson-g12a.rst
@@ -20,8 +20,8 @@
     CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a
 
 This port has been tested on a SEI510 board. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
 mentioned **bl31.img** by the one built from this port.
 
 .. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README.g12a
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/sei510/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/sei510.rst
diff --git a/docs/plat/meson-gxl.rst b/docs/plat/meson-gxl.rst
index c6d8504..0751f1d 100644
--- a/docs/plat/meson-gxl.rst
+++ b/docs/plat/meson-gxl.rst
@@ -20,8 +20,8 @@
     CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl
 
 This port has been tested on a Lepotato. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
 mentioned **bl31.img** by the one built from this port.
 
 .. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/p212/README.libretech-cc
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/p212.rst
diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c
index a705429..a2908d7 100644
--- a/plat/arm/board/arm_fpga/fpga_topology.c
+++ b/plat/arm/board/arm_fpga/fpga_topology.c
@@ -26,7 +26,7 @@
 	fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
 
 	for (i = 0; i < FPGA_MAX_CLUSTER_COUNT; i++) {
-		fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER;
+		fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU;
 	}
 
 	return fpga_power_domain_tree_desc;
@@ -36,35 +36,37 @@
 {
 	unsigned int cluster_id, cpu_id, thread_id;
 
-	mpidr &= MPIDR_AFFINITY_MASK;
-	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
-		return -1;
-	}
+	/*
+	 * The image running on the FPGA may or may not implement
+	 * multithreading, and it shouldn't be assumed this is consistent
+	 * across all CPUs.
+	 * This ensures that any passed mpidr values reflect the status of the
+	 * primary CPU's MT bit.
+	 */
+	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+	mpidr &= MPID_MASK;
 
 	if (mpidr & MPIDR_MT_MASK) {
 		thread_id = MPIDR_AFFLVL0_VAL(mpidr);
+		cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
+		cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
 	} else {
 		thread_id = 0;
+		cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+		cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
 	}
 
-	cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
-	cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
-
 	if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) {
 		return -1;
-	} else if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
-		return -1;
-	} else if (thread_id >= FPGA_MAX_PE_PER_CPU) {
+	}
+
+	if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
 		return -1;
 	}
 
-	/*
-	 * The image running on the FPGA may or may not implement multithreading,
-	 * and it shouldn't be assumed this is consistent across all CPUs.
-	 * This ensures that any passed mpidr values reflect the status of the
-	 * primary CPU's MT bit.
-	 */
-	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+	if (thread_id >= FPGA_MAX_PE_PER_CPU) {
+		return -1;
+	}
 
 	/* Calculate the correct core, catering for multi-threaded images */
 	return (int) plat_fpga_calc_core_pos(mpidr);
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
new file mode 100644
index 0000000..b148666
--- /dev/null
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SHARED_RESOURCES_H
+#define STM32MP_SHARED_RESOURCES_H
+
+#include <stdbool.h>
+
+/* Return true if @clock_id is shared by secure and non-secure worlds */
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
+
+/* Return true if and only if @reset_id relates to a non-secure peripheral */
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
+
+/* Consolidate peripheral states and lock against new peripheral registering */
+void stm32mp_lock_periph_registering(void);
+
+#endif /* STM32MP_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..3f6367e
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <stm32mp_shared_resources.h>
+
+#define STM32MP1_SHRES_GPIOZ(i)		(STM32MP1_SHRES_GPIOZ_0 + (i))
+
+enum stm32mp_shres {
+	STM32MP1_SHRES_CRYP1,
+	STM32MP1_SHRES_GPIOZ_0,
+	STM32MP1_SHRES_GPIOZ_1,
+	STM32MP1_SHRES_GPIOZ_2,
+	STM32MP1_SHRES_GPIOZ_3,
+	STM32MP1_SHRES_GPIOZ_4,
+	STM32MP1_SHRES_GPIOZ_5,
+	STM32MP1_SHRES_GPIOZ_6,
+	STM32MP1_SHRES_GPIOZ_7,
+	STM32MP1_SHRES_HASH1,
+	STM32MP1_SHRES_I2C4,
+	STM32MP1_SHRES_I2C6,
+	STM32MP1_SHRES_IWDG1,
+	STM32MP1_SHRES_MCU,
+	STM32MP1_SHRES_MDMA,
+	STM32MP1_SHRES_PLL3,
+	STM32MP1_SHRES_RNG1,
+	STM32MP1_SHRES_RTC,
+	STM32MP1_SHRES_SPI6,
+	STM32MP1_SHRES_USART1,
+
+	STM32MP1_SHRES_COUNT
+};
+#endif /* STM32MP1_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index de54e09..7327eef 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -6,10 +6,13 @@
 
 SP_MIN_WITH_SECURE_FIQ	:=	1
 
+BL32_CFLAGS		+=	-DSTM32MP_SHARED_RESOURCES
+
 BL32_SOURCES		+=	drivers/st/etzpc/etzpc.c			\
 				plat/common/aarch32/platform_mp_stack.S		\
 				plat/st/stm32mp1/sp_min/sp_min_setup.c		\
 				plat/st/stm32mp1/stm32mp1_pm.c			\
+				plat/st/stm32mp1/stm32mp1_shared_resources.c	\
 				plat/st/stm32mp1/stm32mp1_topology.c
 
 # Generic GIC v2
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 1f96239..9b4c2d2 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -100,19 +100,12 @@
 
 static void stm32mp1_etzpc_early_setup(void)
 {
-	unsigned int n;
-
 	if (etzpc_init() != 0) {
 		panic();
 	}
 
 	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
 	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
-
-	/* Release security on all shared resources */
-	for (n = 0; n < STM32MP1_ETZPC_SEC_ID_LIMIT; n++) {
-		etzpc_configure_decprot(n, ETZPC_DECPROT_NS_RW);
-	}
 }
 
 /*******************************************************************************
@@ -199,14 +192,11 @@
 
 	stm32mp1_gic_init();
 
-	/* Set GPIO bank Z as non secure */
-	for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) {
-		set_gpio_secure_cfg(GPIO_BANK_Z, pin, false);
-	}
-
 	if (stm32_iwdg_init() < 0) {
 		panic();
 	}
+
+	stm32mp_lock_periph_registering();
 }
 
 void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 4fae2d7..ef82d5e 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -25,6 +25,7 @@
 #include <stm32mp_shres_helpers.h>
 #include <stm32mp1_dbgmcu.h>
 #include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
 #endif
 
 /*******************************************************************************
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..268aa52
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+
+#include <stm32mp_shared_resources.h>
+
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+	SHRES_UNREGISTERED = 0,
+	SHRES_SECURE,
+	SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+	registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+	lock_registering();
+
+	return (shres_state[id] == SHRES_NON_SECURE) ||
+	       (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+	return !periph_is_non_secure(id);
+}
+
+/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
+static int8_t gpioz_nbpin = -1;
+
+static unsigned int get_gpio_nbpin(unsigned int bank)
+{
+	if (bank != GPIO_BANK_Z) {
+		int count = fdt_get_gpio_bank_pin_count(bank);
+
+		assert((count >= 0) || (count <= (GPIO_PIN_MAX + 1)));
+
+		return (unsigned int)count;
+	}
+
+	if (gpioz_nbpin < 0) {
+		int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
+
+		assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
+
+		gpioz_nbpin = count;
+	}
+
+	return (unsigned int)gpioz_nbpin;
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+	return get_gpio_nbpin(GPIO_BANK_Z);
+}
+
+/* Currently allow full access by non-secure to platform clock services */
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+	return true;
+}
+
+/* Currently allow full access by non-secure to platform reset services */
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
+{
+	return true;
+}
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+	switch (id) {
+	case STM32MP1_SHRES_MCU:
+	case STM32MP1_SHRES_PLL3:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+	assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+	       (id > STM32MP1_SHRES_GPIOZ(7)));
+
+	if (periph_is_non_secure(id)) {
+		return ETZPC_DECPROT_NS_RW;
+	}
+
+	return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+	/* Some system peripherals shall be secure */
+	etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+
+	/* Configure ETZPC with peripheral registering */
+	etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_HASH1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C4));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C6));
+	etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_RNG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_USART1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+	uint32_t n;
+	uint32_t error = 0U;
+	bool mckprot = stm32mp1_rcc_is_mckprot();
+	bool secure = stm32mp1_rcc_is_secure();
+
+	for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+		if (shres_state[n] != SHRES_SECURE) {
+			continue;
+		}
+
+		if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+			ERROR("RCC %s MCKPROT %s and %u secure\n",
+			      secure ? "secure" : "non-secure",
+			      mckprot ? "set" : "not set",
+			      n);
+			error++;
+		}
+	}
+
+	if (error != 0U) {
+		panic();
+	}
+}
+
+static void set_gpio_secure_configuration(void)
+{
+	uint32_t pin;
+
+	for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+		bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+		set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+	}
+}
+
+static void print_shared_resources_state(void)
+{
+	unsigned int id;
+
+	for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+		switch (shres_state[id]) {
+		case SHRES_SECURE:
+			INFO("stm32mp1 %u is secure\n", id);
+			break;
+		case SHRES_NON_SECURE:
+		case SHRES_UNREGISTERED:
+			VERBOSE("stm32mp %u is non-secure\n", id);
+			break;
+		default:
+			VERBOSE("stm32mp %u is invalid\n", id);
+			panic();
+		}
+	}
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+	registering_locked = true;
+
+	print_shared_resources_state();
+
+	check_rcc_secure_configuration();
+	set_etzpc_secure_configuration();
+	set_gpio_secure_configuration();
+}