1 /* 2 * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <common/debug.h> 10 #include <drivers/arm/cci.h> 11 #include <drivers/arm/ccn.h> 12 #include <drivers/arm/gicv2.h> 13 #include <drivers/arm/sp804_delay_timer.h> 14 #include <drivers/generic_delay_timer.h> 15 #include <fconf_hw_config_getter.h> 16 #include <lib/mmio.h> 17 #include <lib/smccc.h> 18 #include <lib/xlat_tables/xlat_tables_compat.h> 19 #include <platform_def.h> 20 #include <services/arm_arch_svc.h> 21 #include <services/rmm_core_manifest.h> 22 #if SPM_MM 23 #include <services/spm_mm_partition.h> 24 #endif 25 26 #include <plat/arm/common/arm_config.h> 27 #include <plat/arm/common/arm_pas_def.h> 28 #include <plat/arm/common/plat_arm.h> 29 #include <plat/common/platform.h> 30 31 #include "fvp_private.h" 32 33 /* Defines for GIC Driver build time selection */ 34 #define FVP_GICV2 1 35 #define FVP_GICV3 2 36 37 /******************************************************************************* 38 * arm_config holds the characteristics of the differences between the three FVP 39 * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot 40 * at each boot stage by the primary before enabling the MMU (to allow 41 * interconnect configuration) & used thereafter. Each BL will have its own copy 42 * to allow independent operation. 43 ******************************************************************************/ 44 arm_config_t arm_config; 45 46 #define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ 47 DEVICE0_SIZE, \ 48 MT_DEVICE | MT_RW | MT_SECURE) 49 50 #define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ 51 DEVICE1_SIZE, \ 52 MT_DEVICE | MT_RW | MT_SECURE) 53 54 #if FVP_GICR_REGION_PROTECTION 55 #define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \ 56 BASE_GICD_SIZE, \ 57 MT_DEVICE | MT_RW | MT_SECURE) 58 59 /* Map all core's redistributor memory as read-only. After boots up, 60 * per-core map its redistributor memory as read-write */ 61 #define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \ 62 (BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\ 63 MT_DEVICE | MT_RO | MT_SECURE) 64 #endif /* FVP_GICR_REGION_PROTECTION */ 65 66 /* 67 * Need to be mapped with write permissions in order to set a new non-volatile 68 * counter value. 69 */ 70 #define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ 71 DEVICE2_SIZE, \ 72 MT_DEVICE | MT_RW | MT_SECURE) 73 74 #if TRANSFER_LIST 75 #ifdef FW_NS_HANDOFF_BASE 76 #define MAP_FW_NS_HANDOFF MAP_REGION_FLAT(FW_NS_HANDOFF_BASE, \ 77 FW_HANDOFF_SIZE, \ 78 MT_MEMORY | MT_RW | MT_NS) 79 #endif 80 #endif 81 82 /* 83 * Table of memory regions for various BL stages to map using the MMU. 84 * This doesn't include Trusted SRAM as setup_page_tables() already takes care 85 * of mapping it. 86 */ 87 #ifdef IMAGE_BL1 88 const mmap_region_t plat_arm_mmap[] = { 89 ARM_MAP_SHARED_RAM, 90 V2M_MAP_FLASH0_RO, 91 V2M_MAP_IOFPGA, 92 MAP_DEVICE0, 93 #if FVP_INTERCONNECT_DRIVER == FVP_CCN 94 MAP_DEVICE1, 95 #endif 96 #if TRUSTED_BOARD_BOOT 97 /* To access the Root of Trust Public Key registers. */ 98 MAP_DEVICE2, 99 /* Map DRAM to authenticate NS_BL2U image. */ 100 ARM_MAP_NS_DRAM1, 101 #endif 102 {0} 103 }; 104 #endif 105 #ifdef IMAGE_BL2 106 const mmap_region_t plat_arm_mmap[] = { 107 ARM_MAP_SHARED_RAM, 108 V2M_MAP_FLASH0_RW, 109 V2M_MAP_IOFPGA, 110 MAP_DEVICE0, 111 #if FVP_INTERCONNECT_DRIVER == FVP_CCN 112 MAP_DEVICE1, 113 #endif 114 ARM_MAP_NS_DRAM1, 115 #ifdef __aarch64__ 116 ARM_MAP_DRAM2, 117 #endif 118 /* 119 * Required to load HW_CONFIG, SPMC and SPs to trusted DRAM. 120 */ 121 ARM_MAP_TRUSTED_DRAM, 122 123 /* 124 * Required to load Event Log in TZC secured memory 125 */ 126 #if MEASURED_BOOT && (defined(SPD_tspd) || defined(SPD_opteed) || \ 127 defined(SPD_spmd)) 128 ARM_MAP_EVENT_LOG_DRAM1, 129 #endif /* MEASURED_BOOT && (SPD_tspd || SPD_opteed || SPD_spmd) */ 130 131 #if ENABLE_RME 132 ARM_MAP_RMM_DRAM, 133 ARM_MAP_GPT_L1_DRAM, 134 #endif /* ENABLE_RME */ 135 #ifdef SPD_tspd 136 ARM_MAP_TSP_SEC_MEM, 137 #endif 138 #if TRUSTED_BOARD_BOOT 139 /* To access the Root of Trust Public Key registers. */ 140 MAP_DEVICE2, 141 #endif /* TRUSTED_BOARD_BOOT */ 142 143 #if CRYPTO_SUPPORT && !RESET_TO_BL2 144 /* 145 * To access shared the Mbed TLS heap while booting the 146 * system with Crypto support 147 */ 148 ARM_MAP_BL1_RW, 149 #endif /* CRYPTO_SUPPORT && !RESET_TO_BL2 */ 150 #if SPM_MM || SPMC_AT_EL3 151 ARM_SP_IMAGE_MMAP, 152 #endif 153 #if ARM_BL31_IN_DRAM 154 ARM_MAP_BL31_SEC_DRAM, 155 #endif 156 #ifdef SPD_opteed 157 ARM_MAP_OPTEE_CORE_MEM, 158 ARM_OPTEE_PAGEABLE_LOAD_MEM, 159 #endif 160 {0} 161 }; 162 #endif 163 #ifdef IMAGE_BL2U 164 const mmap_region_t plat_arm_mmap[] = { 165 MAP_DEVICE0, 166 V2M_MAP_IOFPGA, 167 {0} 168 }; 169 #endif 170 #ifdef IMAGE_BL31 171 const mmap_region_t plat_arm_mmap[] = { 172 ARM_MAP_SHARED_RAM, 173 #if USE_DEBUGFS 174 /* Required by devfip, can be removed if devfip is not used */ 175 V2M_MAP_FLASH0_RW, 176 #endif /* USE_DEBUGFS */ 177 ARM_MAP_EL3_TZC_DRAM, 178 V2M_MAP_IOFPGA, 179 MAP_DEVICE0, 180 #if FVP_GICR_REGION_PROTECTION 181 MAP_GICD_MEM, 182 MAP_GICR_MEM, 183 #else 184 MAP_DEVICE1, 185 #endif /* FVP_GICR_REGION_PROTECTION */ 186 ARM_V2M_MAP_MEM_PROTECT, 187 #if SPM_MM 188 ARM_SPM_BUF_EL3_MMAP, 189 #endif 190 #if ENABLE_RME 191 ARM_MAP_GPT_L1_DRAM, 192 ARM_MAP_EL3_RMM_SHARED_MEM, 193 #endif 194 #ifdef MAP_FW_NS_HANDOFF 195 MAP_FW_NS_HANDOFF, 196 #endif 197 {0} 198 }; 199 200 #if defined(IMAGE_BL31) && SPM_MM 201 const mmap_region_t plat_arm_secure_partition_mmap[] = { 202 V2M_MAP_IOFPGA_EL0, /* for the UART */ 203 MAP_REGION_FLAT(DEVICE0_BASE, 204 DEVICE0_SIZE, 205 MT_DEVICE | MT_RO | MT_SECURE | MT_USER), 206 ARM_SP_IMAGE_MMAP, 207 ARM_SP_IMAGE_NS_BUF_MMAP, 208 ARM_SP_IMAGE_RW_MMAP, 209 ARM_SPM_BUF_EL0_MMAP, 210 {0} 211 }; 212 #endif 213 #endif 214 #ifdef IMAGE_BL32 215 const mmap_region_t plat_arm_mmap[] = { 216 #ifndef __aarch64__ 217 ARM_MAP_SHARED_RAM, 218 ARM_V2M_MAP_MEM_PROTECT, 219 #endif 220 V2M_MAP_IOFPGA, 221 MAP_DEVICE0, 222 MAP_DEVICE1, 223 {0} 224 }; 225 #endif 226 227 #ifdef IMAGE_RMM 228 const mmap_region_t plat_arm_mmap[] = { 229 V2M_MAP_IOFPGA, 230 MAP_DEVICE0, 231 MAP_DEVICE1, 232 {0} 233 }; 234 #endif 235 236 ARM_CASSERT_MMAP 237 238 #if FVP_INTERCONNECT_DRIVER != FVP_CCN 239 static const int fvp_cci400_map[] = { 240 PLAT_FVP_CCI400_CLUS0_SL_PORT, 241 PLAT_FVP_CCI400_CLUS1_SL_PORT, 242 }; 243 244 static const int fvp_cci5xx_map[] = { 245 PLAT_FVP_CCI5XX_CLUS0_SL_PORT, 246 PLAT_FVP_CCI5XX_CLUS1_SL_PORT, 247 }; 248 249 static unsigned int get_interconnect_master(void) 250 { 251 unsigned int master; 252 u_register_t mpidr; 253 254 mpidr = read_mpidr_el1(); 255 master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ? 256 MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); 257 258 assert(master < FVP_CLUSTER_COUNT); 259 return master; 260 } 261 #endif 262 263 #if defined(IMAGE_BL31) && SPM_MM 264 /* 265 * Boot information passed to a secure partition during initialisation. Linear 266 * indices in MP information will be filled at runtime. 267 */ 268 static spm_mm_mp_info_t sp_mp_info[] = { 269 [0] = {0x80000000, 0}, 270 [1] = {0x80000001, 0}, 271 [2] = {0x80000002, 0}, 272 [3] = {0x80000003, 0}, 273 [4] = {0x80000100, 0}, 274 [5] = {0x80000101, 0}, 275 [6] = {0x80000102, 0}, 276 [7] = {0x80000103, 0}, 277 }; 278 279 const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { 280 .h.type = PARAM_SP_IMAGE_BOOT_INFO, 281 .h.version = VERSION_1, 282 .h.size = sizeof(spm_mm_boot_info_t), 283 .h.attr = 0, 284 .sp_mem_base = ARM_SP_IMAGE_BASE, 285 .sp_mem_limit = ARM_SP_IMAGE_LIMIT, 286 .sp_image_base = ARM_SP_IMAGE_BASE, 287 .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, 288 .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, 289 .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, 290 .sp_shared_buf_base = PLAT_SPM_BUF_BASE, 291 .sp_image_size = ARM_SP_IMAGE_SIZE, 292 .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, 293 .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, 294 .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, 295 .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, 296 .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, 297 .num_cpus = PLATFORM_CORE_COUNT, 298 .mp_info = &sp_mp_info[0], 299 }; 300 301 const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) 302 { 303 return plat_arm_secure_partition_mmap; 304 } 305 306 const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( 307 void *cookie) 308 { 309 return &plat_arm_secure_partition_boot_info; 310 } 311 #endif 312 313 /******************************************************************************* 314 * A single boot loader stack is expected to work on both the Foundation FVP 315 * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The 316 * SYS_ID register provides a mechanism for detecting the differences between 317 * these platforms. This information is stored in a per-BL array to allow the 318 * code to take the correct path.Per BL platform configuration. 319 ******************************************************************************/ 320 void __init fvp_config_setup(void) 321 { 322 unsigned int rev, hbi, bld, arch, sys_id; 323 324 sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); 325 rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK; 326 hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK; 327 bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK; 328 arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; 329 330 if (arch != ARCH_MODEL) { 331 ERROR("This firmware is for FVP models\n"); 332 panic(); 333 } 334 335 /* 336 * The build field in the SYS_ID tells which variant of the GIC 337 * memory is implemented by the model. 338 */ 339 switch (bld) { 340 case BLD_GIC_VE_MMAP: 341 ERROR("Legacy Versatile Express memory map for GIC peripheral" 342 " is not supported\n"); 343 panic(); 344 break; 345 case BLD_GIC_A53A57_MMAP: 346 break; 347 default: 348 ERROR("Unsupported board build %x\n", bld); 349 panic(); 350 } 351 352 /* 353 * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010 354 * for the Foundation FVP. 355 */ 356 switch (hbi) { 357 case HBI_FOUNDATION_FVP: 358 arm_config.flags = 0; 359 360 /* 361 * Check for supported revisions of Foundation FVP 362 * Allow future revisions to run but emit warning diagnostic 363 */ 364 switch (rev) { 365 case REV_FOUNDATION_FVP_V2_0: 366 case REV_FOUNDATION_FVP_V2_1: 367 case REV_FOUNDATION_FVP_v9_1: 368 case REV_FOUNDATION_FVP_v9_6: 369 break; 370 default: 371 WARN("Unrecognized Foundation FVP revision %x\n", rev); 372 break; 373 } 374 break; 375 case HBI_BASE_FVP: 376 arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); 377 378 /* 379 * Check for supported revisions 380 * Allow future revisions to run but emit warning diagnostic 381 */ 382 switch (rev) { 383 case REV_BASE_FVP_V0: 384 arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; 385 break; 386 case REV_BASE_FVP_REVC: 387 arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 | 388 ARM_CONFIG_FVP_HAS_CCI5XX); 389 break; 390 default: 391 WARN("Unrecognized Base FVP revision %x\n", rev); 392 break; 393 } 394 break; 395 default: 396 ERROR("Unsupported board HBI number 0x%x\n", hbi); 397 panic(); 398 } 399 400 /* 401 * We assume that the presence of MT bit, and therefore shifted 402 * affinities, is uniform across the platform: either all CPUs, or no 403 * CPUs implement it. 404 */ 405 if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) 406 arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF; 407 } 408 409 410 void __init fvp_interconnect_init(void) 411 { 412 #if FVP_INTERCONNECT_DRIVER == FVP_CCN 413 if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) { 414 ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported"); 415 panic(); 416 } 417 418 plat_arm_interconnect_init(); 419 #else 420 uintptr_t cci_base = 0U; 421 const int *cci_map = NULL; 422 unsigned int map_size = 0U; 423 424 /* Initialize the right interconnect */ 425 if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) { 426 cci_base = PLAT_FVP_CCI5XX_BASE; 427 cci_map = fvp_cci5xx_map; 428 map_size = ARRAY_SIZE(fvp_cci5xx_map); 429 } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) { 430 cci_base = PLAT_FVP_CCI400_BASE; 431 cci_map = fvp_cci400_map; 432 map_size = ARRAY_SIZE(fvp_cci400_map); 433 } else { 434 return; 435 } 436 437 assert(cci_base != 0U); 438 assert(cci_map != NULL); 439 cci_init(cci_base, cci_map, map_size); 440 #endif 441 } 442 443 void fvp_interconnect_enable(void) 444 { 445 #if FVP_INTERCONNECT_DRIVER == FVP_CCN 446 plat_arm_interconnect_enter_coherency(); 447 #else 448 unsigned int master; 449 450 if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | 451 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { 452 master = get_interconnect_master(); 453 cci_enable_snoop_dvm_reqs(master); 454 } 455 #endif 456 } 457 458 void fvp_interconnect_disable(void) 459 { 460 #if FVP_INTERCONNECT_DRIVER == FVP_CCN 461 plat_arm_interconnect_exit_coherency(); 462 #else 463 unsigned int master; 464 465 if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | 466 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { 467 master = get_interconnect_master(); 468 cci_disable_snoop_dvm_reqs(master); 469 } 470 #endif 471 } 472 473 #if CRYPTO_SUPPORT 474 int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) 475 { 476 assert(heap_addr != NULL); 477 assert(heap_size != NULL); 478 479 return arm_get_mbedtls_heap(heap_addr, heap_size); 480 } 481 #endif /* CRYPTO_SUPPORT */ 482 483 void fvp_timer_init(void) 484 { 485 #if USE_SP804_TIMER 486 /* Enable the clock override for SP804 timer 0, which means that no 487 * clock dividers are applied and the raw (35MHz) clock will be used. 488 */ 489 mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); 490 491 /* Initialize delay timer driver using SP804 dual timer 0 */ 492 sp804_timer_init(V2M_SP804_TIMER0_BASE, 493 SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); 494 #else 495 generic_delay_timer_init(); 496 497 /* Enable System level generic timer */ 498 mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, 499 CNTCR_FCREQ(0U) | CNTCR_EN); 500 #endif /* USE_SP804_TIMER */ 501 } 502 503 /***************************************************************************** 504 * plat_is_smccc_feature_available() - This function checks whether SMCCC 505 * feature is availabile for platform. 506 * @fid: SMCCC function id 507 * 508 * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and 509 * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. 510 *****************************************************************************/ 511 int32_t plat_is_smccc_feature_available(u_register_t fid) 512 { 513 switch (fid) { 514 case SMCCC_ARCH_SOC_ID: 515 return SMC_ARCH_CALL_SUCCESS; 516 default: 517 return SMC_ARCH_CALL_NOT_SUPPORTED; 518 } 519 } 520 521 /* Get SOC version */ 522 int32_t plat_get_soc_version(void) 523 { 524 return (int32_t) 525 (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE, 526 ARM_SOC_IDENTIFICATION_CODE) | 527 (FVP_SOC_ID & SOC_ID_IMPL_DEF_MASK)); 528 } 529 530 /* Get SOC revision */ 531 int32_t plat_get_soc_revision(void) 532 { 533 unsigned int sys_id; 534 535 sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); 536 return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) & 537 V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK); 538 } 539 540 #if ENABLE_RME 541 /* 542 * Get a pointer to the RMM-EL3 Shared buffer and return it 543 * through the pointer passed as parameter. 544 * 545 * This function returns the size of the shared buffer. 546 */ 547 size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared) 548 { 549 *shared = (uintptr_t)RMM_SHARED_BASE; 550 551 return (size_t)RMM_SHARED_SIZE; 552 } 553 554 int plat_rmmd_load_manifest(struct rmm_manifest *manifest) 555 { 556 uint64_t checksum, num_banks; 557 struct ns_dram_bank *bank_ptr; 558 559 assert(manifest != NULL); 560 561 /* Get number of DRAM banks */ 562 num_banks = FCONF_GET_PROPERTY(hw_config, dram_layout, num_banks); 563 assert(num_banks <= ARM_DRAM_NUM_BANKS); 564 565 manifest->version = RMMD_MANIFEST_VERSION; 566 manifest->padding = 0U; /* RES0 */ 567 manifest->plat_data = (uintptr_t)NULL; 568 manifest->plat_dram.num_banks = num_banks; 569 570 /* 571 * Array ns_dram_banks[] follows ns_dram_info structure: 572 * 573 * +-----------------------------------+ 574 * | offset | field | comment | 575 * +----------+-----------+------------+ 576 * | 0 | version | 0x00000002 | 577 * +----------+-----------+------------+ 578 * | 4 | padding | 0x00000000 | 579 * +----------+-----------+------------+ 580 * | 8 | plat_data | NULL | 581 * +----------+-----------+------------+ 582 * | 16 | num_banks | | 583 * +----------+-----------+ | 584 * | 24 | banks | plat_dram | 585 * +----------+-----------+ | 586 * | 32 | checksum | | 587 * +----------+-----------+------------+ 588 * | 40 | base 0 | | 589 * +----------+-----------+ bank[0] | 590 * | 48 | size 0 | | 591 * +----------+-----------+------------+ 592 * | 56 | base 1 | | 593 * +----------+-----------+ bank[1] | 594 * | 64 | size 1 | | 595 * +----------+-----------+------------+ 596 */ 597 bank_ptr = (struct ns_dram_bank *) 598 ((uintptr_t)&manifest->plat_dram.checksum + 599 sizeof(manifest->plat_dram.checksum)); 600 601 manifest->plat_dram.banks = bank_ptr; 602 603 /* Calculate checksum of plat_dram structure */ 604 checksum = num_banks + (uint64_t)bank_ptr; 605 606 /* Store FVP DRAM banks data in Boot Manifest */ 607 for (unsigned long i = 0UL; i < num_banks; i++) { 608 uintptr_t base = FCONF_GET_PROPERTY(hw_config, dram_layout, dram_bank[i].base); 609 uint64_t size = FCONF_GET_PROPERTY(hw_config, dram_layout, dram_bank[i].size); 610 611 bank_ptr[i].base = base; 612 bank_ptr[i].size = size; 613 614 /* Update checksum */ 615 checksum += base + size; 616 } 617 618 /* Checksum must be 0 */ 619 manifest->plat_dram.checksum = ~checksum + 1UL; 620 621 return 0; 622 } 623 #endif /* ENABLE_RME */ 624