summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/user-guide.md8
-rw-r--r--drivers/arm/ccn/ccn.c13
-rw-r--r--drivers/arm/ccn/ccn_private.h1
-rw-r--r--include/drivers/arm/ccn.h8
-rw-r--r--plat/arm/board/fvp/fvp_common.c11
-rw-r--r--plat/arm/board/fvp/fvp_def.h19
-rw-r--r--plat/arm/board/fvp/include/plat_macros.S2
-rw-r--r--plat/arm/board/fvp/include/platform_def.h4
-rw-r--r--plat/arm/board/fvp/platform.mk22
-rw-r--r--plat/arm/common/arm_ccn.c3
10 files changed, 84 insertions, 7 deletions
diff --git a/docs/user-guide.md b/docs/user-guide.md
index cd9c8c33..ce0390d8 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -496,6 +496,14 @@ map is explained in the [Firmware Design].
for functions that wait for an arbitrary time length (udelay and mdelay).
The default value is 0.
+* `FVP_INTERCONNECT_DRIVER`: Selects the interconnect driver to be built. The
+ default interconnect driver depends on the value of `FVP_CLUSTER_COUNT` as
+ explained in the options below:
+ - `FVP_CCI` : The CCI driver is selected. This is the default
+ if 0 < `FVP_CLUSTER_COUNT` <= 2.
+ - `FVP_CCN` : The CCN driver is selected. This is the default
+ if `FVP_CLUSTER_COUNT` > 2.
+
### Debugging options
To compile a debug version and make the build more verbose use
diff --git a/drivers/arm/ccn/ccn.c b/drivers/arm/ccn/ccn.c
index 28d27098..060acdd2 100644
--- a/drivers/arm/ccn/ccn.c
+++ b/drivers/arm/ccn/ccn.c
@@ -254,6 +254,7 @@ static unsigned long long ccn_master_to_rn_id_map(unsigned long long master_map)
assert(ccn_plat_desc);
FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, master_map) {
+ assert(iface_id < ccn_plat_desc->num_masters);
/* Convert the master ID into the node ID */
node_id = ccn_plat_desc->master_to_rn_id_map[iface_id];
@@ -501,3 +502,15 @@ void ccn_program_sys_addrmap(unsigned int sn0_id,
}
}
+
+/*******************************************************************************
+ * This function returns the part0 id from the peripheralID 0 register
+ * in CCN. This id can be used to distinguish the CCN variant present in the
+ * system.
+ ******************************************************************************/
+int ccn_get_part0_id(uintptr_t periphbase)
+{
+ assert(periphbase);
+ return (int)(mmio_read_64(periphbase
+ + MN_PERIPH_ID_0_1_OFFSET) & 0xFF);
+}
diff --git a/drivers/arm/ccn/ccn_private.h b/drivers/arm/ccn/ccn_private.h
index 8b154725..fffa2ca9 100644
--- a/drivers/arm/ccn/ccn_private.h
+++ b/drivers/arm/ccn/ccn_private.h
@@ -149,6 +149,7 @@ typedef enum rn_types {
#define MN_DDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET
#define MN_DDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET
#define MN_DDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET
+#define MN_PERIPH_ID_0_1_OFFSET 0xFE0
#define MN_ID_OFFSET REGION_ID_OFFSET
/* HNF System Address Map register bit masks and shifts */
diff --git a/include/drivers/arm/ccn.h b/include/drivers/arm/ccn.h
index 23615966..85c45c68 100644
--- a/include/drivers/arm/ccn.h
+++ b/include/drivers/arm/ccn.h
@@ -51,6 +51,13 @@
#define CCN_L3_RUN_MODE_HAM 0x2 /* HNF_PM_HALF */
#define CCN_L3_RUN_MODE_FAM 0x3 /* HNF_PM_FULL */
+/* part 0 IDs for various CCN variants */
+#define CCN_502_PART0_ID 0x30
+#define CCN_504_PART0_ID 0x26
+#define CCN_505_PART0_ID 0x27
+#define CCN_508_PART0_ID 0x28
+#define CCN_512_PART0_ID 0x29
+
/*
* The following macro takes the value returned from a read of a HN-F P-state
* status register and returns the retention state value.
@@ -107,6 +114,7 @@ void ccn_program_sys_addrmap(unsigned int sn0_id,
unsigned int top_addr_bit1,
unsigned char three_sn_en);
unsigned int ccn_get_l3_run_mode(void);
+int ccn_get_part0_id(uintptr_t periphbase);
#endif /* __ASSEMBLY__ */
#endif /* __CCN_H__ */
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 78782d43..eb67dab2 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -30,6 +30,7 @@
#include <arm_config.h>
#include <arm_def.h>
+#include <ccn.h>
#include <debug.h>
#include <gicv2.h>
#include <mmio.h>
@@ -213,8 +214,16 @@ void fvp_config_setup(void)
void fvp_interconnect_init(void)
{
- if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT)
+ if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT) {
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+ if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
+ ERROR("Unrecognized CCN variant detected. Only CCN-502"
+ " is supported");
+ panic();
+ }
+#endif
plat_arm_interconnect_init();
+ }
}
void fvp_interconnect_enable(void)
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index b0f07ef5..40d20fce 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -40,6 +40,10 @@
#define FVP_PRIMARY_CPU 0x0
+/* Defines for the Interconnect build selection */
+#define FVP_CCI 1
+#define FVP_CCN 2
+
/*******************************************************************************
* FVP memory map related constants
******************************************************************************/
@@ -57,16 +61,23 @@
#define DEVICE0_BASE 0x20000000
#define DEVICE0_SIZE 0x0c200000
+/*
+ * In case of FVP models with CCN, the CCN register space overlaps into
+ * the NSRAM area.
+ */
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+#define DEVICE1_BASE 0x2e000000
+#define DEVICE1_SIZE 0x1A00000
+#else
#define DEVICE1_BASE 0x2f000000
#define DEVICE1_SIZE 0x200000
-
+#define NSRAM_BASE 0x2e000000
+#define NSRAM_SIZE 0x10000
+#endif
/* Devices in the second GB */
#define DEVICE2_BASE 0x7fe00000
#define DEVICE2_SIZE 0x00200000
-#define NSRAM_BASE 0x2e000000
-#define NSRAM_SIZE 0x10000
-
#define PCIE_EXP_BASE 0x40000000
#define TZRNG_BASE 0x7fe60000
diff --git a/plat/arm/board/fvp/include/plat_macros.S b/plat/arm/board/fvp/include/plat_macros.S
index e43c7acf..657a39b9 100644
--- a/plat/arm/board/fvp/include/plat_macros.S
+++ b/plat/arm/board/fvp/include/plat_macros.S
@@ -64,7 +64,9 @@ use_ve_mmap:
mov_imm x16, VE_GICD_BASE
print_gic_regs:
arm_print_gic_regs
+#if FVP_INTERCONNECT_DRIVER == FVP_CCI
print_cci_regs
+#endif
.endm
#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index ca8e35e3..1e906d82 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -90,6 +90,10 @@
#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 3
#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 4
+/* CCN related constants. Only CCN 502 is currently supported */
+#define PLAT_ARM_CCN_BASE 0x2e000000
+#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP 1, 5, 7, 11
+
/* System timer related constants */
#define PLAT_ARM_NSTIMER_FRAME_ID 1
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c0fe662e..6456cdea 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -39,11 +39,22 @@ $(eval $(call add_define,FVP_USE_SP804_TIMER))
# The FVP platform depends on this macro to build with correct GIC driver.
$(eval $(call add_define,FVP_USE_GIC_DRIVER))
-# If FVP_CLUSTER_COUNT has been defined, pass it into the build system.
-ifdef FVP_CLUSTER_COUNT
+# Define default FVP_CLUSTER_COUNT to 2 and pass it into the build system.
+FVP_CLUSTER_COUNT := 2
$(eval $(call add_define,FVP_CLUSTER_COUNT))
+
+# Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2,
+# choose the CCI driver , else the CCN driver
+ifeq ($(FVP_CLUSTER_COUNT), 0)
+$(error "Incorrect cluster count specified for FVP port")
+else ifeq ($(FVP_CLUSTER_COUNT),$(filter $(FVP_CLUSTER_COUNT),1 2))
+FVP_INTERCONNECT_DRIVER := FVP_CCI
+else
+FVP_INTERCONNECT_DRIVER := FVP_CCN
endif
+$(eval $(call add_define,FVP_INTERCONNECT_DRIVER))
+
# Choose the GIC sources depending upon the how the FVP will be invoked
ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
@@ -67,8 +78,15 @@ else
$(error "Incorrect GIC driver chosen on FVP port")
endif
+ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCI)
FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
+else ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCN)
+FVP_INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \
+ plat/arm/common/arm_ccn.c
+else
+$(error "Incorrect CCN driver chosen on FVP port")
+endif
FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/fvp/fvp_security.c \
diff --git a/plat/arm/common/arm_ccn.c b/plat/arm/common/arm_ccn.c
index 5cb443aa..fe10d7b5 100644
--- a/plat/arm/common/arm_ccn.c
+++ b/plat/arm/common/arm_ccn.c
@@ -43,6 +43,9 @@ static const ccn_desc_t arm_ccn_desc = {
.master_to_rn_id_map = master_to_rn_id_map
};
+CASSERT(PLAT_ARM_CLUSTER_COUNT == ARRAY_SIZE(master_to_rn_id_map),
+ assert_invalid_cluster_count_for_ccn_variant);
+
/******************************************************************************
* The following functions are defined as weak to allow a platform to override
* the way ARM CCN driver is initialised and used.