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