Merge "GCC: Upgrade to version 9.2-2019.12 of toolchain" into integration
diff --git a/Makefile b/Makefile
index 073c2ed..42fdb73 100644
--- a/Makefile
+++ b/Makefile
@@ -736,6 +736,7 @@
 $(eval $(call assert_boolean,RESET_TO_BL31))
 $(eval $(call assert_boolean,SAVE_KEYS))
 $(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA))
+$(eval $(call assert_boolean,SEPARATE_NOBITS_REGION))
 $(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
 $(eval $(call assert_boolean,SPM_MM))
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
@@ -800,6 +801,7 @@
 $(eval $(call add_define,RAS_EXTENSION))
 $(eval $(call add_define,RESET_TO_BL31))
 $(eval $(call add_define,SEPARATE_CODE_AND_RODATA))
+$(eval $(call add_define,SEPARATE_NOBITS_REGION))
 $(eval $(call add_define,RECLAIM_INIT_CODE))
 $(eval $(call add_define,SPD_${SPD}))
 $(eval $(call add_define,SPIN_ON_BL1_EXIT))
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index a598e59..42227f0 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -15,6 +15,11 @@
 
 MEMORY {
     RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE
+#if SEPARATE_NOBITS_REGION
+    NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE
+#else
+#define NOBITS RAM
+#endif
 }
 
 #ifdef PLAT_EXTRA_LD_SCRIPT
@@ -198,11 +203,28 @@
     ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.")
 #endif
 
+#if SEPARATE_NOBITS_REGION
+    /*
+     * Define a linker symbol to mark end of the RW memory area for this
+     * image.
+     */
+    __RW_END__ = .;
+    __BL31_END__ = .;
+
+    ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
+
+    . = BL31_NOBITS_BASE;
+    ASSERT(. == ALIGN(PAGE_SIZE),
+           "BL31 NOBITS base address is not aligned on a page boundary.")
+
+    __NOBITS_START__ = .;
+#endif
+
     stacks (NOLOAD) : {
         __STACKS_START__ = .;
         *(tzfw_normal_stacks)
         __STACKS_END__ = .;
-    } >RAM
+    } >NOBITS
 
     /*
      * The .bss section gets initialised to 0 at runtime.
@@ -262,7 +284,7 @@
         __PMF_TIMESTAMP_END__ = .;
 #endif /* ENABLE_PMF */
         __BSS_END__ = .;
-    } >RAM
+    } >NOBITS
 
     /*
      * The xlat_table section is for full, aligned page tables (4K).
@@ -272,7 +294,7 @@
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
-    } >RAM
+    } >NOBITS
 
 #if USE_COHERENT_MEM
     /*
@@ -298,9 +320,18 @@
          */
         . = ALIGN(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
-    } >RAM
+    } >NOBITS
 #endif
 
+#if SEPARATE_NOBITS_REGION
+    /*
+     * Define a linker symbol to mark end of the NOBITS memory area for this
+     * image.
+     */
+    __NOBITS_END__ = .;
+
+    ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.")
+#else
     /*
      * Define a linker symbol to mark end of the RW memory area for this
      * image.
@@ -309,4 +340,5 @@
     __BL31_END__ = .;
 
     ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
+#endif
 }
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index cae94b5..5fc1335 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -1500,6 +1500,11 @@
 this NOBITS section, making the image unnecessarily bigger. Smaller images
 allow faster loading from the FIP to the main memory.
 
+For BL31, a platform can specify an alternate location for NOBITS sections
+(other than immediately following PROGBITS sections) by setting
+``SEPARATE_NOBITS_REGION`` to 1 and defining ``BL31_NOBITS_BASE`` and
+``BL31_NOBITS_LIMIT``.
+
 Linker scripts and symbols
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 37c28a5..d7bb044 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -491,6 +491,13 @@
    pages" section in :ref:`Firmware Design`. This flag is disabled by default and
    affects all BL images.
 
+-  ``SEPARATE_NOBITS_REGION``: Setting this option to ``1`` allows the NOBITS
+   sections of BL31 (.bss, stacks, page tables, and coherent memory) to be
+   allocated in RAM discontiguous from the loaded firmware image. When set, the
+   platform is expected to provide definitons for ``BL31_NOBITS_BASE`` and
+   ``BL31_NOBITS_LIMIT``. When the option is ``0`` (the default), NOBITS
+   sections are placed in RAM immediately following the loaded firmware image.
+
 -  ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A.
    This build option is only valid if ``ARCH=aarch64``. The value should be
    the path to the directory containing the SPD source, relative to
diff --git a/drivers/arm/scu/scu.c b/drivers/arm/scu/scu.c
new file mode 100644
index 0000000..aceac92
--- /dev/null
+++ b/drivers/arm/scu/scu.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <drivers/arm/scu.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Turn ON snoop control unit. This is needed to synchronize the data between
+ * CPU's.
+ ******************************************************************************/
+void enable_snoop_ctrl_unit(uintptr_t base)
+{
+	uint32_t scu_ctrl;
+
+	INFO("[SCU]: enabling snoop control unit ... \n");
+
+	assert(base != 0U);
+	scu_ctrl = mmio_read_32(base + SCU_CTRL_REG);
+
+	/* already enabled? */
+	if ((scu_ctrl & SCU_ENABLE_BIT) != 0) {
+		return;
+	}
+
+	scu_ctrl |= SCU_ENABLE_BIT;
+	mmio_write_32(base + SCU_CTRL_REG, scu_ctrl);
+}
+
+/*******************************************************************************
+ * Snoop Control Unit configuration register. This is read-only register and
+ * contains information such as
+ * - number of CPUs present
+ * - is a particular CPU operating in SMP mode or AMP mode
+ * - data cache size of a particular CPU
+ * - does SCU has ACP port
+ * - is L2CPRESENT
+ * NOTE: user of this API should interpert the bits in this register according
+ * to the TRM
+ ******************************************************************************/
+uint32_t read_snoop_ctrl_unit_cfg(uintptr_t base)
+{
+	assert(base != 0U);
+
+	return mmio_read_32(base + SCU_CFG_REG);
+}
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index b14b7b6..156b18a 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -382,6 +382,14 @@
 		add	x1, x1, :lo12:__RW_END__
 		sub	x1, x1, x0
 		bl	inv_dcache_range
+#if defined(IMAGE_BL31) && SEPARATE_NOBITS_REGION
+		adrp	x0, __NOBITS_START__
+		add	x0, x0, :lo12:__NOBITS_START__
+		adrp	x1, __NOBITS_END__
+		add	x1, x1, :lo12:__NOBITS_END__
+		sub	x1, x1, x0
+		bl	inv_dcache_range
+#endif
 #endif
 		adrp	x0, __BSS_START__
 		add	x0, x0, :lo12:__BSS_START__
diff --git a/include/drivers/arm/scu.h b/include/drivers/arm/scu.h
new file mode 100644
index 0000000..992539f
--- /dev/null
+++ b/include/drivers/arm/scu.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCU_H
+#define SCU_H
+
+#include <stdint.h>
+
+#define SCU_CTRL_REG	0x00
+#define SCU_CFG_REG	0x04
+
+#define SCU_ENABLE_BIT	(1 << 0)
+
+void enable_snoop_ctrl_unit(uintptr_t base);
+uint32_t read_snoop_ctrl_unit_cfg(uintptr_t base);
+
+#endif /* SCU_H */
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index a1f9db9..53832c5 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -171,6 +171,10 @@
 # platform Makefile is free to override this value.
 SEPARATE_CODE_AND_RODATA	:= 0
 
+# Put NOBITS sections (.bss, stacks, page tables, and coherent memory) in a
+# separate memory region, which may be discontiguous from the rest of BL31.
+SEPARATE_NOBITS_REGION		:= 0
+
 # If the BL31 image initialisation code is recalimed after use for the secondary
 # cores stack
 RECLAIM_INIT_CODE		:= 0
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 5e8885d..d281011 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -8,8 +8,7 @@
 
 AW_PLAT			:=	plat/allwinner
 
-PLAT_INCLUDES		:=	-Iinclude/plat/arm/common		\
-				-Iinclude/plat/arm/common/aarch64	\
+PLAT_INCLUDES		:=	-Iinclude/plat/arm/common/aarch64	\
 				-I${AW_PLAT}/common/include		\
 				-I${AW_PLAT}/${PLAT}/include
 
diff --git a/plat/arm/board/a5ds/a5ds_pm.c b/plat/arm/board/a5ds/a5ds_pm.c
index cc734b0..7774002 100644
--- a/plat/arm/board/a5ds/a5ds_pm.c
+++ b/plat/arm/board/a5ds/a5ds_pm.c
@@ -4,11 +4,10 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <assert.h>
-
+#include <drivers/arm/gicv2.h>
 #include <lib/psci/psci.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
-#include <drivers/arm/gicv2.h>
 
 /*******************************************************************************
  * Platform handler called when a power domain is about to be turned on. The
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index e9e4b9a..d200af6 100644
--- a/plat/arm/board/a5ds/include/platform_def.h
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -334,6 +334,9 @@
 #define A5DS_HOLD_STATE_WAIT	0
 #define A5DS_HOLD_STATE_GO	1
 
+/* Snoop Control Unit base address */
+#define A5DS_SCU_BASE			0x1C000000
+
 /*
  * GIC related constants to cater for GICv2
  */
diff --git a/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c b/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c
index 8b45af8..a951dc7 100644
--- a/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c
+++ b/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c
@@ -4,12 +4,17 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <drivers/arm/scu.h>
 #include <plat/arm/common/plat_arm.h>
 
+
 void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
 			u_register_t arg2, u_register_t arg3)
 {
 	arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+	/* enable snoop control unit */
+	enable_snoop_ctrl_unit(A5DS_SCU_BASE);
 }
 
 /*
diff --git a/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
index da1d785..4b0c97d 100644
--- a/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
+++ b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
@@ -5,7 +5,8 @@
 #
 
 # SP_MIN source files specific to A5DS platform
-BL32_SOURCES	+=	drivers/cfi/v2m/v2m_flash.c			\
+BL32_SOURCES	+=	drivers/arm/scu/scu.c                           \
+			drivers/cfi/v2m/v2m_flash.c			\
 			lib/utils/mem_region.c				\
 			lib/aarch32/arm32_aeabi_divmod.c		\
 			lib/aarch32/arm32_aeabi_divmod_a32.S		\
diff --git a/plat/mediatek/mt8183/drivers/spm/spm.c b/plat/mediatek/mt8183/drivers/spm/spm.c
index 547af57..d6d2344 100644
--- a/plat/mediatek/mt8183/drivers/spm/spm.c
+++ b/plat/mediatek/mt8183/drivers/spm/spm.c
@@ -12,6 +12,12 @@
 
 DEFINE_BAKERY_LOCK(spm_lock);
 
+/* SPM_DVS_LEVEL */
+#define SPM_VMODEM_LEVEL_MASK	(0xff << 16)
+#define SPM_VMODEM_LEVEL	(1U << 18)
+#define SPM_VCORE_LEVEL_MASK	(0xff)
+#define SPM_VCORE_LEVEL		(1U << 1)
+
 /* CLK_SCP_CFG_0 */
 #define SPM_CK_OFF_CONTROL	(0x3FF)
 
@@ -339,6 +345,11 @@
 	spm_lock_init();
 	mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
 
+	/* Set Vmodem / Vcore DVS init level */
+	mmio_clrsetbits_32(SPM_DVS_LEVEL,
+			   SPM_VMODEM_LEVEL_MASK | SPM_VCORE_LEVEL_MASK,
+			   SPM_VMODEM_LEVEL | SPM_VCORE_LEVEL);
+
 	/* switch ck_off/axi_26m control to SPM */
 	mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_OFF_CONTROL);
 	mmio_setbits_32(CLK_SCP_CFG_1, SPM_AXI_26M_SEL);
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 0c5cfae..0219422 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -59,6 +59,9 @@
 include lib/coreboot/coreboot.mk
 include lib/libfdt/libfdt.mk
 
+# Enable workarounds for selected Cortex-A53 errata
+ERRATA_A53_855873	:=	1
+
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
 $(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))