diff --git a/docs/user-guide.md b/docs/user-guide.md index cd9c8c33e..ce0390d8e 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 28d270984..060acdd20 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 8b1547256..fffa2ca94 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 236159668..85c45c684 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 78782d430..eb67dab2b 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -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 b0f07ef51..40d20fce7 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 e43c7acfc..657a39b9c 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 ca8e35e32..1e906d82b 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 c0fe662e0..6456cdeaa 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 5cb443aa5..fe10d7b52 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.