1 /* 2 * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */ 8 #define XLAT_TABLES_LIB_V2 1 9 10 #include <assert.h> 11 #include <common/debug.h> 12 13 #include <drivers/arm/cci.h> 14 #include <drivers/arm/gicv2.h> 15 #include <drivers/arm/sp804_delay_timer.h> 16 #include <drivers/generic_delay_timer.h> 17 #include <lib/mmio.h> 18 #include <lib/smccc.h> 19 #include <lib/xlat_tables/xlat_tables_compat.h> 20 #include <services/arm_arch_svc.h> 21 22 #include "fvp_r_private.h" 23 #include <plat/arm/common/arm_config.h> 24 #include <plat/arm/common/plat_arm.h> 25 #include <plat/common/platform.h> 26 #include <platform_def.h> 27 28 29 /* Defines for GIC Driver build time selection */ 30 #define FVP_R_GICV3 2 31 32 /******************************************************************************* 33 * arm_config holds the characteristics of the differences between the FVP_R 34 * platforms. It will be populated during cold boot at each boot stage by the 35 * primary before enabling the MPU (to allow interconnect configuration) & 36 * used thereafter. Each BL will have its own copy to allow independent 37 * operation. 38 ******************************************************************************/ 39 arm_config_t arm_config; 40 41 #define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ 42 DEVICE0_SIZE, \ 43 MT_DEVICE | MT_RW | MT_SECURE) 44 45 #define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ 46 DEVICE1_SIZE, \ 47 MT_DEVICE | MT_RW | MT_SECURE) 48 49 /* 50 * Need to be mapped with write permissions in order to set a new non-volatile 51 * counter value. 52 */ 53 #define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ 54 DEVICE2_SIZE, \ 55 MT_DEVICE | MT_RW | MT_SECURE) 56 57 /* 58 * Table of memory regions for various BL stages to map using the MPU. 59 * This doesn't include Trusted SRAM as setup_page_tables() already takes care 60 * of mapping it. 61 * 62 * The flash needs to be mapped as writable in order to erase the FIP's Table of 63 * Contents in case of unrecoverable error (see plat_error_handler()). 64 */ 65 #ifdef IMAGE_BL1 66 const mmap_region_t plat_arm_mmap[] = { 67 ARM_MAP_SHARED_RAM, 68 V2M_MAP_FLASH0_RW, 69 V2M_MAP_IOFPGA, 70 MAP_DEVICE0, 71 MAP_DEVICE1, 72 #if TRUSTED_BOARD_BOOT 73 /* To access the Root of Trust Public Key registers. */ 74 MAP_DEVICE2, 75 #endif 76 {0} 77 }; 78 #endif 79 80 ARM_CASSERT_MMAP 81 82 static const int fvp_cci400_map[] = { 83 PLAT_FVP_R_CCI400_CLUS0_SL_PORT, 84 PLAT_FVP_R_CCI400_CLUS1_SL_PORT, 85 }; 86 87 static const int fvp_cci5xx_map[] = { 88 PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT, 89 PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT, 90 }; 91 92 static unsigned int get_interconnect_master(void) 93 { 94 unsigned int master; 95 u_register_t mpidr; 96 97 mpidr = read_mpidr_el1(); 98 master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ? 99 MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); 100 101 assert(master < FVP_R_CLUSTER_COUNT); 102 return master; 103 } 104 105 /******************************************************************************* 106 * Initialize the platform config for future decision making 107 ******************************************************************************/ 108 void __init fvp_config_setup(void) 109 { 110 unsigned int rev, hbi, bld, arch, sys_id; 111 112 arm_config.flags |= ARM_CONFIG_BASE_MMAP; 113 sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID); 114 rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK; 115 hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK; 116 bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK; 117 arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; 118 119 if (arch != ARCH_MODEL) { 120 ERROR("This firmware is for FVP_R models\n"); 121 panic(); 122 } 123 124 /* 125 * The build field in the SYS_ID tells which variant of the GIC 126 * memory is implemented by the model. 127 */ 128 switch (bld) { 129 case BLD_GIC_VE_MMAP: 130 ERROR("Legacy Versatile Express memory map for GIC %s", 131 "peripheral is not supported\n"); 132 panic(); 133 break; 134 case BLD_GIC_A53A57_MMAP: 135 break; 136 default: 137 ERROR("Unsupported board build %x\n", bld); 138 panic(); 139 } 140 141 /* 142 * The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010 143 * for the Foundation FVP_R. 144 */ 145 switch (hbi) { 146 case HBI_FOUNDATION_FVP_R: 147 arm_config.flags = 0; 148 149 /* 150 * Check for supported revisions of Foundation FVP_R 151 * Allow future revisions to run but emit warning diagnostic 152 */ 153 switch (rev) { 154 case REV_FOUNDATION_FVP_R_V2_0: 155 case REV_FOUNDATION_FVP_R_V2_1: 156 case REV_FOUNDATION_FVP_R_v9_1: 157 case REV_FOUNDATION_FVP_R_v9_6: 158 break; 159 default: 160 WARN("Unrecognized Foundation FVP_R revision %x\n", rev); 161 break; 162 } 163 break; 164 case HBI_BASE_FVP_R: 165 arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); 166 167 /* 168 * Check for supported revisions 169 * Allow future revisions to run but emit warning diagnostic 170 */ 171 switch (rev) { 172 case REV_BASE_FVP_R_V0: 173 arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; 174 break; 175 default: 176 WARN("Unrecognized Base FVP_R revision %x\n", rev); 177 break; 178 } 179 break; 180 default: 181 ERROR("Unsupported board HBI number 0x%x\n", hbi); 182 panic(); 183 } 184 185 /* 186 * We assume that the presence of MT bit, and therefore shifted 187 * affinities, is uniform across the platform: either all CPUs, or no 188 * CPUs implement it. 189 */ 190 if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) { 191 arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF; 192 } 193 } 194 195 196 void __init fvp_interconnect_init(void) 197 { 198 uintptr_t cci_base = 0U; 199 const int *cci_map = NULL; 200 unsigned int map_size = 0U; 201 202 /* Initialize the right interconnect */ 203 if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) { 204 cci_base = PLAT_FVP_R_CCI5XX_BASE; 205 cci_map = fvp_cci5xx_map; 206 map_size = ARRAY_SIZE(fvp_cci5xx_map); 207 } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) { 208 cci_base = PLAT_FVP_R_CCI400_BASE; 209 cci_map = fvp_cci400_map; 210 map_size = ARRAY_SIZE(fvp_cci400_map); 211 } else { 212 return; 213 } 214 215 assert(cci_base != 0U); 216 assert(cci_map != NULL); 217 cci_init(cci_base, cci_map, map_size); 218 } 219 220 void fvp_interconnect_enable(void) 221 { 222 unsigned int master; 223 224 if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | 225 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { 226 master = get_interconnect_master(); 227 cci_enable_snoop_dvm_reqs(master); 228 } 229 } 230 231 void fvp_interconnect_disable(void) 232 { 233 unsigned int master; 234 235 if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | 236 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { 237 master = get_interconnect_master(); 238 cci_disable_snoop_dvm_reqs(master); 239 } 240 } 241 242 #if TRUSTED_BOARD_BOOT 243 int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) 244 { 245 assert(heap_addr != NULL); 246 assert(heap_size != NULL); 247 248 return arm_get_mbedtls_heap(heap_addr, heap_size); 249 } 250 #endif 251 252 void fvp_timer_init(void) 253 { 254 #if USE_SP804_TIMER 255 /* Enable the clock override for SP804 timer 0, which means that no 256 * clock dividers are applied and the raw (35MHz) clock will be used. 257 */ 258 mmio_write_32(V2M_SP810_BASE, FVP_R_SP810_CTRL_TIM0_OV); 259 260 /* Initialize delay timer driver using SP804 dual timer 0 */ 261 sp804_timer_init(V2M_SP804_TIMER0_BASE, 262 SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); 263 #else 264 generic_delay_timer_init(); 265 266 /* Enable System level generic timer */ 267 mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, 268 CNTCR_FCREQ(0U) | CNTCR_EN); 269 #endif /* USE_SP804_TIMER */ 270 } 271 272 /* Get SOC version */ 273 int32_t plat_get_soc_version(void) 274 { 275 return (int32_t) 276 ((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT) 277 | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT) 278 | FVP_R_SOC_ID); 279 } 280 281 /* Get SOC revision */ 282 int32_t plat_get_soc_revision(void) 283 { 284 unsigned int sys_id; 285 286 sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); 287 return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) & 288 V2M_SYS_ID_REV_MASK); 289 } 290