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();
+}