feat(msm8916): initialize CCI-400 for multiple clusters

The MSM8939 SoC is very similar to MSM8916 but uses an ARM CCI-400
for cache coherence between the two CPU clusters. Add the necessary
code to initialize it with the existing driver.

No functional change for platforms with a single cluster. The CCI
related code is discarded entirely in this case.

Change-Id: I041d60222d8d2aeca53b392934c87280c66b0db0
Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
diff --git a/plat/qti/msm8916/include/msm8916_mmap.h b/plat/qti/msm8916/include/msm8916_mmap.h
index 5cb2f44..20c5a57 100644
--- a/plat/qti/msm8916/include/msm8916_mmap.h
+++ b/plat/qti/msm8916/include/msm8916_mmap.h
@@ -43,4 +43,9 @@
 #define APCS_ALIAS_ACS(cluster, cpu)	(_APCS_CPU(cluster, cpu) + 0x88000)
 #define APCS_ALIAS_SAW2(cluster, cpu)	(_APCS_CPU(cluster, cpu) + 0x89000)
 
+/* Only on platforms with multiple clusters (e.g. MSM8939) */
+#define APCS_CCI_BASE		(APCS_BASE + 0x1c0000)
+#define APCS_CCI_SAW2		(APCS_BASE + 0x1d2000)
+#define APCS_CCI_ACS		(APCS_BASE + 0x1d4000)
+
 #endif /* MSM8916_MMAP_H */
diff --git a/plat/qti/msm8916/msm8916_bl31_setup.c b/plat/qti/msm8916/msm8916_bl31_setup.c
index 449be7f..c588020 100644
--- a/plat/qti/msm8916/msm8916_bl31_setup.c
+++ b/plat/qti/msm8916/msm8916_bl31_setup.c
@@ -33,6 +33,7 @@
 				u_register_t arg2, u_register_t arg3)
 {
 	msm8916_early_platform_setup();
+	msm8916_configure_early();
 }
 
 void bl31_plat_arch_setup(void)
diff --git a/plat/qti/msm8916/msm8916_config.c b/plat/qti/msm8916/msm8916_config.c
index 47eede2..b37fd19 100644
--- a/plat/qti/msm8916/msm8916_config.c
+++ b/plat/qti/msm8916/msm8916_config.c
@@ -7,6 +7,7 @@
 #include <assert.h>
 
 #include <arch.h>
+#include <drivers/arm/cci.h>
 #include <lib/mmio.h>
 
 #include "msm8916_config.h"
@@ -14,6 +15,16 @@
 #include <msm8916_mmap.h>
 #include <platform_def.h>
 
+static const int cci_map[] = { 3, 4 };
+
+void msm8916_configure_early(void)
+{
+	if (PLATFORM_CLUSTER_COUNT > 1) {
+		cci_init(APCS_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+	}
+}
+
 static void msm8916_configure_timer(uintptr_t base)
 {
 	/* Set timer frequency */
@@ -81,6 +92,12 @@
 	for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; cluster++) {
 		msm8916_configure_apcs_cluster(cluster);
 	}
+
+	if (PLATFORM_CLUSTER_COUNT > 1) {
+		/* Disallow non-secure access to CCI ACS and SAW2 */
+		mmio_write_32(APCS_CCI_ACS, 0);
+		mmio_write_32(APCS_CCI_SAW2, 0);
+	}
 }
 
 /*
diff --git a/plat/qti/msm8916/msm8916_config.h b/plat/qti/msm8916/msm8916_config.h
index 992625b..977d02c 100644
--- a/plat/qti/msm8916/msm8916_config.h
+++ b/plat/qti/msm8916/msm8916_config.h
@@ -8,5 +8,6 @@
 #define MSM8916_CONFIG_H
 
 void msm8916_configure(void);
+void msm8916_configure_early(void);
 
 #endif /* MSM8916_CONFIG_H */
diff --git a/plat/qti/msm8916/msm8916_pm.c b/plat/qti/msm8916/msm8916_pm.c
index 6267344..79c670f 100644
--- a/plat/qti/msm8916/msm8916_pm.c
+++ b/plat/qti/msm8916/msm8916_pm.c
@@ -7,6 +7,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/arm/cci.h>
 #include <drivers/arm/gicv2.h>
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
@@ -29,6 +30,8 @@
 #define MPIDR_APCS_CLUSTER(mpidr)	0
 #endif
 
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+
 static int msm8916_pwr_domain_on(u_register_t mpidr)
 {
 	msm8916_cpu_boot(APCS_ALIAS_ACS(MPIDR_APCS_CLUSTER(mpidr),
@@ -38,6 +41,11 @@
 
 static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
+	if (PLATFORM_CLUSTER_COUNT > 1 &&
+	    CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+	}
+
 	gicv2_pcpu_distif_init();
 	gicv2_cpuif_enable();
 }
diff --git a/plat/qti/msm8916/platform.mk b/plat/qti/msm8916/platform.mk
index 2110494..9432435 100644
--- a/plat/qti/msm8916/platform.mk
+++ b/plat/qti/msm8916/platform.mk
@@ -18,7 +18,8 @@
 				plat/qti/msm8916/${ARCH}/uartdm_console.S
 
 MSM8916_CPU		:=	$(if ${ARM_CORTEX_A7},cortex_a7,cortex_a53)
-MSM8916_PM_SOURCES	:=	lib/cpus/${ARCH}/${MSM8916_CPU}.S		\
+MSM8916_PM_SOURCES	:=	drivers/arm/cci/cci.c				\
+				lib/cpus/${ARCH}/${MSM8916_CPU}.S		\
 				plat/common/plat_psci_common.c			\
 				plat/qti/msm8916/msm8916_config.c		\
 				plat/qti/msm8916/msm8916_cpu_boot.c		\
diff --git a/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c b/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c
index 78ab0c7..3c93305 100644
--- a/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c
+++ b/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c
@@ -27,6 +27,7 @@
 				  u_register_t arg2, u_register_t arg3)
 {
 	msm8916_early_platform_setup();
+	msm8916_configure_early();
 }
 
 void sp_min_plat_arch_setup(void)