Merge pull request #1702 from MISL-EBU-System-SW/patches-18.12

Update code with latest changes from Marvell LSP 18.12
diff --git a/drivers/arm/ccn/ccn.c b/drivers/arm/ccn/ccn.c
index 910cd7c..59a7576 100644
--- a/drivers/arm/ccn/ccn.c
+++ b/drivers/arm/ccn/ccn.c
@@ -11,6 +11,7 @@
 #include <debug.h>
 #include <errno.h>
 #include <mmio.h>
+#include <stdbool.h>
 #include "ccn_private.h"
 
 static const ccn_desc_t *ccn_plat_desc;
@@ -490,3 +491,123 @@
 	return (int)(mmio_read_64(periphbase
 			+ MN_PERIPH_ID_0_1_OFFSET) & 0xFF);
 }
+
+/*******************************************************************************
+ * This function returns the region id corresponding to a node_id of node_type.
+ ******************************************************************************/
+static unsigned int get_region_id_for_node(node_types_t node_type,
+						unsigned int node_id)
+{
+	unsigned int mn_reg_off, region_id;
+	unsigned long long node_bitmap;
+	unsigned int loc_node_id, node_pos_in_map = 0;
+
+	assert(node_type < NUM_NODE_TYPES);
+	assert(node_id < MAX_RN_NODES);
+
+	switch (node_type) {
+	case NODE_TYPE_RNI:
+		region_id = RNI_REGION_ID_START;
+		break;
+	case NODE_TYPE_HNF:
+		region_id = HNF_REGION_ID_START;
+		break;
+	case NODE_TYPE_HNI:
+		region_id = HNI_REGION_ID_START;
+		break;
+	case NODE_TYPE_SN:
+		region_id = SBSX_REGION_ID_START;
+		break;
+	default:
+		ERROR("Un-supported Node Type = %d.\n", node_type);
+		assert(false);
+		return REGION_ID_LIMIT;
+	}
+	/*
+	 * RN-I, HN-F, HN-I, SN node registers in the MN region
+	 * occupy contiguous 16 byte apart offsets.
+	 *
+	 * RN-F and RN-D node are not supported as
+	 * none of them exposes any memory map to
+	 * configure any of their offset registers.
+	 */
+
+	mn_reg_off = MN_RNF_NODEID_OFFSET + (node_type << 4);
+	node_bitmap = ccn_reg_read(ccn_plat_desc->periphbase,
+					MN_REGION_ID, mn_reg_off);
+
+	assert((node_bitmap & (1ULL << (node_id))) != 0U);
+
+
+	FOR_EACH_PRESENT_NODE_ID(loc_node_id, node_bitmap) {
+		INFO("Index = %u with loc_nod=%u and input nod=%u\n",
+					node_pos_in_map, loc_node_id, node_id);
+		if (loc_node_id == node_id)
+			break;
+		node_pos_in_map++;
+	}
+
+	if (node_pos_in_map == CCN_MAX_RN_MASTERS) {
+		ERROR("Node Id = %d, is not found.\n", node_id);
+		assert(false);
+		return REGION_ID_LIMIT;
+	}
+
+	region_id += node_pos_in_map;
+
+	return region_id;
+}
+
+/*******************************************************************************
+ * This function sets the value 'val' to the register at register_offset from
+ * the base address pointed to by the region_id.
+ * where, region id is mapped to a node_id of node_type.
+ ******************************************************************************/
+void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
+			unsigned int reg_offset, unsigned long long val)
+{
+	unsigned int region_id = get_region_id_for_node(node_type, node_id);
+
+	if (reg_offset > REGION_ID_OFFSET) {
+		ERROR("Invalid Register offset 0x%x is provided.\n",
+								reg_offset);
+		assert(false);
+		return;
+	}
+
+	/* Setting the value of Auxilary Control Register of the Node */
+	ccn_reg_write(ccn_plat_desc->periphbase, region_id, reg_offset, val);
+	VERBOSE("Value is successfully written at address 0x%lx.\n",
+			(ccn_plat_desc->periphbase
+			+ region_id_to_base(region_id))
+			+ reg_offset);
+}
+
+/*******************************************************************************
+ * This function read the value 'val' stored in the register at register_offset
+ * from the base address pointed to by the region_id.
+ * where, region id is mapped to a node_id of node_type.
+ ******************************************************************************/
+unsigned long long ccn_read_node_reg(node_types_t node_type,
+					unsigned int node_id,
+					unsigned int reg_offset)
+{
+	unsigned long long val;
+	unsigned int region_id = get_region_id_for_node(node_type, node_id);
+
+	if (reg_offset > REGION_ID_OFFSET) {
+		ERROR("Invalid Register offset 0x%x is provided.\n",
+								reg_offset);
+		assert(false);
+		return ULL(0);
+	}
+
+	/* Setting the value of Auxilary Control Register of the Node */
+	val = ccn_reg_read(ccn_plat_desc->periphbase, region_id, reg_offset);
+	VERBOSE("Value is successfully read from address 0x%lx.\n",
+			(ccn_plat_desc->periphbase
+			+ region_id_to_base(region_id))
+			+ reg_offset);
+
+	return val;
+}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 418ab11..02bf770 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -246,6 +246,13 @@
 			return ret;
 		}
 
+		do {
+			ret = mmc_device_state();
+			if (ret < 0) {
+				return ret;
+			}
+		} while (ret != MMC_STATE_TRAN);
+
 		nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) |
 			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
 			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
diff --git a/include/drivers/arm/ccn.h b/include/drivers/arm/ccn.h
index eba974d..9c3abac 100644
--- a/include/drivers/arm/ccn.h
+++ b/include/drivers/arm/ccn.h
@@ -76,6 +76,16 @@
 	uintptr_t periphbase;
 } ccn_desc_t;
 
+/* Enum used to loop through all types of nodes in CCN*/
+typedef enum node_types {
+	NODE_TYPE_RNF = 0,
+	NODE_TYPE_RNI,
+	NODE_TYPE_RND,
+	NODE_TYPE_HNF,
+	NODE_TYPE_HNI,
+	NODE_TYPE_SN,
+	NUM_NODE_TYPES
+} node_types_t;
 
 void ccn_init(const ccn_desc_t *plat_ccn_desc);
 void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map);
@@ -92,5 +102,12 @@
 unsigned int ccn_get_l3_run_mode(void);
 int ccn_get_part0_id(uintptr_t periphbase);
 
+void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
+				unsigned int reg_offset,
+				unsigned long long val);
+unsigned long long ccn_read_node_reg(node_types_t node_type,
+					unsigned int node_id,
+					unsigned int reg_offset);
+
 #endif /* __ASSEMBLY__ */
 #endif /* CCN_H */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 02963ac..2b48967 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -162,4 +162,11 @@
 
 #define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory")
 
+/* Compiler builtin of GCC >= 9 and planned in llvm */
+#ifdef __HAVE_SPECULATION_SAFE_VALUE
+# define SPECULATION_SAFE_VALUE(var) __builtin_speculation_safe_value(var)
+#else
+# define SPECULATION_SAFE_VALUE(var) var
+#endif
+
 #endif /* UTILS_DEF_H */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index d02a405..cbac247 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -34,6 +34,7 @@
 #define ARM_PWR_LVL0		MPIDR_AFFLVL0
 #define ARM_PWR_LVL1		MPIDR_AFFLVL1
 #define ARM_PWR_LVL2		MPIDR_AFFLVL2
+#define ARM_PWR_LVL3		MPIDR_AFFLVL3
 
 /*
  *  Macros for local power states in ARM platforms encoded by State-ID field
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index eeb72de..ff75c69 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -11,9 +11,6 @@
 #include <psci.h>
 #include <stdint.h>
 
-/* System power domain at level 2, as currently implemented by CSS platforms */
-#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
-
 /* Macros to read the CSS power domain state */
 #define CSS_CORE_PWR_STATE(state)	(state)->pwr_domain_state[ARM_PWR_LVL0]
 #define CSS_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[ARM_PWR_LVL1]
diff --git a/lib/psci/psci_stat.c b/lib/psci/psci_stat.c
index 421db44..6f6a7d4 100644
--- a/lib/psci/psci_stat.c
+++ b/lib/psci/psci_stat.c
@@ -206,9 +206,9 @@
 
 	if (pwrlvl > PSCI_CPU_PWR_LVL) {
 		/* Get the power domain index */
-		parent_idx = psci_cpu_pd_nodes[target_idx].parent_node;
+		parent_idx = SPECULATION_SAFE_VALUE(psci_cpu_pd_nodes[target_idx].parent_node);
 		for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl < pwrlvl; lvl++)
-			parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
+			parent_idx = SPECULATION_SAFE_VALUE(psci_non_cpu_pd_nodes[parent_idx].parent_node);
 
 		/* Get the non cpu power domain stats */
 		*psci_stat = psci_non_cpu_stat[parent_idx][stat_idx];
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 7b85043..78d3025 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -416,3 +416,8 @@
 	.read_mem_protect	= arm_psci_read_mem_protect,
 	.write_mem_protect	= arm_nor_psci_write_mem_protect,
 };
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return ops;
+}
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 0bbe3e1..8098bc3 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -295,4 +295,7 @@
 #define PLAT_ARM_PRIVATE_SDEI_EVENTS	ARM_SDEI_PRIVATE_EVENTS
 #define PLAT_ARM_SHARED_SDEI_EVENTS	ARM_SDEI_SHARED_EVENTS
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c
new file mode 100644
index 0000000..da2e92b
--- /dev/null
+++ b/plat/arm/board/juno/juno_pm.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_arm.h>
+#include <scmi.h>
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index ba1acd4..ad955f6 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -27,6 +27,7 @@
 CSS_USE_SCMI_SDS_DRIVER		:=	1
 
 PLAT_INCLUDES		:=	-Iplat/arm/board/juno/include		\
+				-Iplat/arm/css/drivers/scmi		\
 				-Iplat/arm/css/drivers/sds
 
 PLAT_BL_COMMON_SOURCES	:=	plat/arm/board/juno/${ARCH}/juno_helpers.S \
@@ -79,6 +80,7 @@
 				lib/cpus/aarch64/cortex_a57.S		\
 				lib/cpus/aarch64/cortex_a72.S		\
 				lib/utils/mem_region.c			\
+				plat/arm/board/juno/juno_pm.c		\
 				plat/arm/board/juno/juno_topology.c	\
 				plat/arm/common/arm_nor_psci_mem_protect.c \
 				${JUNO_GIC_SOURCES}			\
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index 5278109..b3471c1 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -10,6 +10,7 @@
 			lib/cpus/aarch32/cortex_a57.S		\
 			lib/cpus/aarch32/cortex_a72.S		\
 			lib/utils/mem_region.c			\
+			plat/arm/board/juno/juno_pm.c		\
 			plat/arm/board/juno/juno_topology.c	\
 			plat/arm/common/arm_nor_psci_mem_protect.c	\
 			plat/arm/soc/common/soc_css_security.c	\
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 3e48397..fa639ca 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -32,6 +32,8 @@
 						N1SDP_MAX_CPUS_PER_CLUSTER *	\
 						N1SDP_MAX_PE_PER_CPU)
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL			ARM_PWR_LVL2
 
 /*
  * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index 65aad9c..cdd0b63 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -6,6 +6,7 @@
 
 #include "../../css/drivers/scmi/scmi.h"
 #include "../../css/drivers/mhu/css_mhu_doorbell.h"
+#include <plat_arm.h>
 #include <platform_def.h>
 
 static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
@@ -20,3 +21,8 @@
 {
 	return &n1sdp_scmi_plat_info;
 }
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index c06a0a1..16e2898 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -20,4 +20,9 @@
 #define SGI575_DMC620_BASE0		UL(0x4e000000)
 #define SGI575_DMC620_BASE1		UL(0x4e100000)
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h
index ba6d043..39907e8 100644
--- a/plat/arm/board/sgiclarka/include/platform_def.h
+++ b/plat/arm/board/sgiclarka/include/platform_def.h
@@ -20,4 +20,9 @@
 #define SGICLARKA_DMC620_BASE0		UL(0x4e000000)
 #define SGICLARKA_DMC620_BASE1		UL(0x4e100000)
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 6394bfb..3be1b5d 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -14,7 +14,6 @@
 #include <psci.h>
 
 /* Allow ARM Standard platforms to override these functions */
-#pragma weak plat_arm_psci_override_pm_ops
 #pragma weak plat_arm_program_trusted_mailbox
 
 #if !ARM_RECOM_STATE_ID_ENC
@@ -133,14 +132,6 @@
 }
 
 /******************************************************************************
- * Default definition on ARM standard platforms to override the plat_psci_ops.
- *****************************************************************************/
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
-{
-	return ops;
-}
-
-/******************************************************************************
  * Helper function to save the platform state before a system suspend. Save the
  * state of the system components which are not in the Always ON power domain.
  *****************************************************************************/
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index e1358bf..28dfc9a 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -8,6 +8,7 @@
 #define SCMI_H
 
 #include <bakery_lock.h>
+#include <psci.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <spinlock.h>
@@ -162,4 +163,7 @@
 /* API to get the platform specific SCMI channel information. */
 scmi_channel_plat_info_t *plat_css_get_scmi_info();
 
+/* API to override default PSCI callbacks for platforms that support SCMI. */
+const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops);
+
 #endif /* SCMI_H */
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index 956f583..1397fd8 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -339,7 +339,7 @@
  * the SCMI driver, query capability via SCMI and modify the PSCI capability
  * based on that.
  *****************************************************************************/
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops)
 {
 	uint32_t msg_attr;
 	int ret;
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 1395373..8705d63 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -119,8 +119,6 @@
 #define PLAT_ARM_NSRAM_BASE		0x06000000
 #define PLAT_ARM_NSRAM_SIZE		0x00080000	/* 512KB */
 
-#define PLAT_MAX_PWR_LVL		U(1)
-
 #define PLAT_ARM_G1S_IRQ_PROPS(grp)	CSS_G1S_IRQ_PROPS(grp)
 #define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
 
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index ce85026..d44f89c 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -101,3 +101,8 @@
 	sgi_ras_intr_handler_setup();
 #endif
 }
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
index 3b7a57a..e524f11 100644
--- a/plat/arm/css/sgi/sgi_topology.c
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -44,3 +44,11 @@
 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,		\
 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
 };
+
+/******************************************************************************
+ * Return the number of PE's supported by the CPU.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+	return CSS_SGI_MAX_PE_PER_CPU;
+}
diff --git a/plat/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index a9795a4..2178f06 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -239,4 +239,8 @@
  */
 #define PLAT_ARM_MEM_PROT_ADDR		(V2M_FLASH0_BASE + \
 					 V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
 #endif /* SGM_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgm/sgm_bl31_setup.c b/plat/arm/css/sgm/sgm_bl31_setup.c
index 29c32e7..952572e 100644
--- a/plat/arm/css/sgm/sgm_bl31_setup.c
+++ b/plat/arm/css/sgm/sgm_bl31_setup.c
@@ -47,3 +47,8 @@
 
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index d42afe0..125d665 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -336,7 +336,6 @@
 	params.flags = MMC_FLAG_CMD23;
 	info.mmc_dev_type = MMC_IS_EMMC;
 	dw_mmc_init(&params, &info);
-	mdelay(20);
 
 	hikey_io_setup();
 }