From 6331a31a66cdcf53421d3dccd3067f072c6da175 Mon Sep 17 00:00:00 2001 From: Soby Mathew Date: Wed, 23 Mar 2016 17:14:57 +0000 Subject: [PATCH 1/2] CCN: Add API to query the PART0 ID from CCN This patch adds the API `ccn_get_part0_id` to query the PART0 ID from the PERIPHERAL_ID 0 register in the CCN driver. This ID allows to distinguish the variant of CCN present on the system and possibly enable dynamic configuration of the IP based on the variant. Also added an assert in `ccn_master_to_rn_id_map()` to ensure that the master map bitfield provided by the platform is within the expected interface id. Change-Id: I92d2db7bd93a9be8a7fbe72a522cbcba0aba2d0e --- drivers/arm/ccn/ccn.c | 13 +++++++++++++ drivers/arm/ccn/ccn_private.h | 1 + include/drivers/arm/ccn.h | 8 ++++++++ 3 files changed, 22 insertions(+) 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__ */ From 7123787616e21871319909508e80594c7f24f6b8 Mon Sep 17 00:00:00 2001 From: Soby Mathew Date: Thu, 24 Mar 2016 10:12:42 +0000 Subject: [PATCH 2/2] Add CCN support to FVP platform port This patch adds support to select CCN driver for FVP during build. A new build option `FVP_INTERCONNECT_DRIVER` is added to allow selection between the CCI and CCN driver. Currently only the CCN-502 variant is supported on FVP. The common ARM CCN platform helper file now verifies the cluster count declared by platform is equal to the number of root node masters exported by the ARM Standard platform. Change-Id: I71d7b4785f8925ed499c153b2e9b9925fcefd57a --- docs/user-guide.md | 8 ++++++++ plat/arm/board/fvp/fvp_common.c | 11 ++++++++++- plat/arm/board/fvp/fvp_def.h | 19 +++++++++++++++---- plat/arm/board/fvp/include/plat_macros.S | 2 ++ plat/arm/board/fvp/include/platform_def.h | 4 ++++ plat/arm/board/fvp/platform.mk | 22 ++++++++++++++++++++-- plat/arm/common/arm_ccn.c | 3 +++ 7 files changed, 62 insertions(+), 7 deletions(-) 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/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.