1 /* 2 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch.h> 32 #include <arch_helpers.h> 33 #include <arm_gic.h> 34 #include <bl_common.h> 35 #include <cci400.h> 36 #include <debug.h> 37 #include <mmio.h> 38 #include <platform.h> 39 #include <platform_def.h> 40 #include <plat_config.h> 41 #include <xlat_tables.h> 42 #include "../fvp_def.h" 43 44 /******************************************************************************* 45 * plat_config holds the characteristics of the differences between the three 46 * FVP platforms (Base, A53_A57 & Foundation). It will be populated during cold 47 * boot at each boot stage by the primary before enabling the MMU (to allow cci 48 * configuration) & used thereafter. Each BL will have its own copy to allow 49 * independent operation. 50 ******************************************************************************/ 51 plat_config_t plat_config; 52 53 #define MAP_SHARED_RAM MAP_REGION_FLAT(FVP_SHARED_MEM_BASE, \ 54 FVP_SHARED_MEM_SIZE, \ 55 MT_MEMORY | MT_RW | MT_SECURE) 56 57 #define MAP_FLASH0 MAP_REGION_FLAT(FLASH0_BASE, \ 58 FLASH0_SIZE, \ 59 MT_MEMORY | MT_RO | MT_SECURE) 60 61 #define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ 62 DEVICE0_SIZE, \ 63 MT_DEVICE | MT_RW | MT_SECURE) 64 65 #define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ 66 DEVICE1_SIZE, \ 67 MT_DEVICE | MT_RW | MT_SECURE) 68 69 #define MAP_DRAM1_NS MAP_REGION_FLAT(DRAM1_NS_BASE, \ 70 DRAM1_NS_SIZE, \ 71 MT_MEMORY | MT_RW | MT_NS) 72 73 #define MAP_TSP_SEC_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ 74 TSP_SEC_MEM_SIZE, \ 75 MT_MEMORY | MT_RW | MT_SECURE) 76 77 /* 78 * Table of regions for various BL stages to map using the MMU. 79 * This doesn't include TZRAM as the 'mem_layout' argument passed to 80 * configure_mmu_elx() will give the available subset of that, 81 */ 82 #if IMAGE_BL1 83 const mmap_region_t fvp_mmap[] = { 84 MAP_SHARED_RAM, 85 MAP_FLASH0, 86 MAP_DEVICE0, 87 MAP_DEVICE1, 88 {0} 89 }; 90 #endif 91 #if IMAGE_BL2 92 const mmap_region_t fvp_mmap[] = { 93 MAP_SHARED_RAM, 94 MAP_FLASH0, 95 MAP_DEVICE0, 96 MAP_DEVICE1, 97 MAP_DRAM1_NS, 98 MAP_TSP_SEC_MEM, 99 {0} 100 }; 101 #endif 102 #if IMAGE_BL31 103 const mmap_region_t fvp_mmap[] = { 104 MAP_SHARED_RAM, 105 MAP_DEVICE0, 106 MAP_DEVICE1, 107 MAP_TSP_SEC_MEM, 108 {0} 109 }; 110 #endif 111 #if IMAGE_BL32 112 const mmap_region_t fvp_mmap[] = { 113 MAP_DEVICE0, 114 MAP_DEVICE1, 115 {0} 116 }; 117 #endif 118 119 /* Array of secure interrupts to be configured by the gic driver */ 120 const unsigned int irq_sec_array[] = { 121 IRQ_TZ_WDOG, 122 IRQ_SEC_PHY_TIMER, 123 IRQ_SEC_SGI_0, 124 IRQ_SEC_SGI_1, 125 IRQ_SEC_SGI_2, 126 IRQ_SEC_SGI_3, 127 IRQ_SEC_SGI_4, 128 IRQ_SEC_SGI_5, 129 IRQ_SEC_SGI_6, 130 IRQ_SEC_SGI_7 131 }; 132 133 const unsigned int num_sec_irqs = sizeof(irq_sec_array) / 134 sizeof(irq_sec_array[0]); 135 136 /******************************************************************************* 137 * Macro generating the code for the function setting up the pagetables as per 138 * the platform memory map & initialize the mmu, for the given exception level 139 ******************************************************************************/ 140 #if USE_COHERENT_MEM 141 #define DEFINE_CONFIGURE_MMU_EL(_el) \ 142 void fvp_configure_mmu_el##_el(unsigned long total_base, \ 143 unsigned long total_size, \ 144 unsigned long ro_start, \ 145 unsigned long ro_limit, \ 146 unsigned long coh_start, \ 147 unsigned long coh_limit) \ 148 { \ 149 mmap_add_region(total_base, total_base, \ 150 total_size, \ 151 MT_MEMORY | MT_RW | MT_SECURE); \ 152 mmap_add_region(ro_start, ro_start, \ 153 ro_limit - ro_start, \ 154 MT_MEMORY | MT_RO | MT_SECURE); \ 155 mmap_add_region(coh_start, coh_start, \ 156 coh_limit - coh_start, \ 157 MT_DEVICE | MT_RW | MT_SECURE); \ 158 mmap_add(fvp_mmap); \ 159 init_xlat_tables(); \ 160 \ 161 enable_mmu_el##_el(0); \ 162 } 163 #else 164 #define DEFINE_CONFIGURE_MMU_EL(_el) \ 165 void fvp_configure_mmu_el##_el(unsigned long total_base, \ 166 unsigned long total_size, \ 167 unsigned long ro_start, \ 168 unsigned long ro_limit) \ 169 { \ 170 mmap_add_region(total_base, total_base, \ 171 total_size, \ 172 MT_MEMORY | MT_RW | MT_SECURE); \ 173 mmap_add_region(ro_start, ro_start, \ 174 ro_limit - ro_start, \ 175 MT_MEMORY | MT_RO | MT_SECURE); \ 176 mmap_add(fvp_mmap); \ 177 init_xlat_tables(); \ 178 \ 179 enable_mmu_el##_el(0); \ 180 } 181 #endif 182 183 /* Define EL1 and EL3 variants of the function initialising the MMU */ 184 DEFINE_CONFIGURE_MMU_EL(1) 185 DEFINE_CONFIGURE_MMU_EL(3) 186 187 /******************************************************************************* 188 * A single boot loader stack is expected to work on both the Foundation FVP 189 * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The 190 * SYS_ID register provides a mechanism for detecting the differences between 191 * these platforms. This information is stored in a per-BL array to allow the 192 * code to take the correct path.Per BL platform configuration. 193 ******************************************************************************/ 194 int fvp_config_setup(void) 195 { 196 unsigned int rev, hbi, bld, arch, sys_id; 197 198 sys_id = mmio_read_32(VE_SYSREGS_BASE + V2M_SYS_ID); 199 rev = (sys_id >> SYS_ID_REV_SHIFT) & SYS_ID_REV_MASK; 200 hbi = (sys_id >> SYS_ID_HBI_SHIFT) & SYS_ID_HBI_MASK; 201 bld = (sys_id >> SYS_ID_BLD_SHIFT) & SYS_ID_BLD_MASK; 202 arch = (sys_id >> SYS_ID_ARCH_SHIFT) & SYS_ID_ARCH_MASK; 203 204 if (arch != ARCH_MODEL) { 205 ERROR("This firmware is for FVP models\n"); 206 panic(); 207 } 208 209 /* 210 * The build field in the SYS_ID tells which variant of the GIC 211 * memory is implemented by the model. 212 */ 213 switch (bld) { 214 case BLD_GIC_VE_MMAP: 215 plat_config.gicd_base = VE_GICD_BASE; 216 plat_config.gicc_base = VE_GICC_BASE; 217 plat_config.gich_base = VE_GICH_BASE; 218 plat_config.gicv_base = VE_GICV_BASE; 219 break; 220 case BLD_GIC_A53A57_MMAP: 221 plat_config.gicd_base = BASE_GICD_BASE; 222 plat_config.gicc_base = BASE_GICC_BASE; 223 plat_config.gich_base = BASE_GICH_BASE; 224 plat_config.gicv_base = BASE_GICV_BASE; 225 break; 226 default: 227 ERROR("Unsupported board build %x\n", bld); 228 panic(); 229 } 230 231 /* 232 * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010 233 * for the Foundation FVP. 234 */ 235 switch (hbi) { 236 case HBI_FOUNDATION: 237 plat_config.max_aff0 = 4; 238 plat_config.max_aff1 = 1; 239 plat_config.flags = 0; 240 241 /* 242 * Check for supported revisions of Foundation FVP 243 * Allow future revisions to run but emit warning diagnostic 244 */ 245 switch (rev) { 246 case REV_FOUNDATION_V2_0: 247 case REV_FOUNDATION_V2_1: 248 break; 249 default: 250 WARN("Unrecognized Foundation FVP revision %x\n", rev); 251 break; 252 } 253 break; 254 case HBI_FVP_BASE: 255 plat_config.max_aff0 = 4; 256 plat_config.max_aff1 = 2; 257 plat_config.flags |= CONFIG_BASE_MMAP | CONFIG_HAS_CCI | 258 CONFIG_HAS_TZC; 259 260 /* 261 * Check for supported revisions 262 * Allow future revisions to run but emit warning diagnostic 263 */ 264 switch (rev) { 265 case REV_FVP_BASE_V0: 266 break; 267 default: 268 WARN("Unrecognized Base FVP revision %x\n", rev); 269 break; 270 } 271 break; 272 default: 273 ERROR("Unsupported board HBI number 0x%x\n", hbi); 274 panic(); 275 } 276 277 return 0; 278 } 279 280 unsigned long plat_get_ns_image_entrypoint(void) 281 { 282 return NS_IMAGE_OFFSET; 283 } 284 285 uint64_t plat_get_syscnt_freq(void) 286 { 287 uint64_t counter_base_frequency; 288 289 /* Read the frequency from Frequency modes table */ 290 counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF); 291 292 /* The first entry of the frequency modes table must not be 0 */ 293 if (counter_base_frequency == 0) 294 panic(); 295 296 return counter_base_frequency; 297 } 298 299 void fvp_cci_init(void) 300 { 301 /* 302 * Initialize CCI-400 driver 303 */ 304 if (plat_config.flags & CONFIG_HAS_CCI) 305 cci_init(CCI400_BASE, 306 CCI400_SL_IFACE3_CLUSTER_IX, 307 CCI400_SL_IFACE4_CLUSTER_IX); 308 } 309 310 void fvp_cci_enable(void) 311 { 312 /* 313 * Enable CCI-400 coherency for this cluster. No need 314 * for locks as no other cpu is active at the 315 * moment 316 */ 317 if (plat_config.flags & CONFIG_HAS_CCI) 318 cci_enable_cluster_coherency(read_mpidr()); 319 } 320 321 void fvp_gic_init(void) 322 { 323 arm_gic_init(plat_config.gicc_base, 324 plat_config.gicd_base, 325 BASE_GICR_BASE, 326 irq_sec_array, 327 num_sec_irqs); 328 } 329 330 331 /******************************************************************************* 332 * Gets SPSR for BL32 entry 333 ******************************************************************************/ 334 uint32_t fvp_get_spsr_for_bl32_entry(void) 335 { 336 /* 337 * The Secure Payload Dispatcher service is responsible for 338 * setting the SPSR prior to entry into the BL32 image. 339 */ 340 return 0; 341 } 342 343 /******************************************************************************* 344 * Gets SPSR for BL33 entry 345 ******************************************************************************/ 346 uint32_t fvp_get_spsr_for_bl33_entry(void) 347 { 348 unsigned long el_status; 349 unsigned int mode; 350 uint32_t spsr; 351 352 /* Figure out what mode we enter the non-secure world in */ 353 el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; 354 el_status &= ID_AA64PFR0_ELX_MASK; 355 356 if (el_status) 357 mode = MODE_EL2; 358 else 359 mode = MODE_EL1; 360 361 /* 362 * TODO: Consider the possibility of specifying the SPSR in 363 * the FIP ToC and allowing the platform to have a say as 364 * well. 365 */ 366 spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 367 return spsr; 368 } 369