1 /* 2 * Copyright (c) 2022, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <drivers/arm/css/sds.h> 9 #include <lib/mmio.h> 10 #include <lib/utils.h> 11 12 #include "n1sdp_def.h" 13 #include <plat/arm/common/plat_arm.h> 14 15 struct n1sdp_plat_info { 16 bool multichip_mode; 17 uint8_t secondary_count; 18 uint8_t local_ddr_size; 19 uint8_t remote_ddr_size; 20 } __packed; 21 22 /* 23 * N1SDP platform supports RDIMMs with ECC capability. To use the ECC 24 * capability, the entire DDR memory space has to be zeroed out before 25 * enabling the ECC bits in DMC620. Zeroing out several gigabytes of 26 * memory from SCP is quite time consuming so the following function 27 * is added to zero out the DDR memory from application processor which is 28 * much faster compared to SCP. 29 */ 30 31 void dmc_ecc_setup(uint8_t ddr_size_gb) 32 { 33 uint64_t dram2_size; 34 35 dram2_size = (ddr_size_gb * 1024UL * 1024UL * 1024UL) - 36 ARM_DRAM1_SIZE; 37 38 INFO("Zeroing DDR memories\n"); 39 zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); 40 flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); 41 zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); 42 flush_dcache_range(ARM_DRAM2_BASE, dram2_size); 43 44 INFO("Enabling ECC on DMCs\n"); 45 /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ 46 mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); 47 mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); 48 49 /* Enable ECC in DMCs */ 50 mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); 51 mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); 52 53 /* Set DMCs to READY state */ 54 mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); 55 mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); 56 } 57 58 void bl2_platform_setup(void) 59 { 60 int ret; 61 struct n1sdp_plat_info plat_info; 62 63 ret = sds_init(); 64 if (ret != SDS_OK) { 65 ERROR("SDS initialization failed\n"); 66 panic(); 67 } 68 69 ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, 70 N1SDP_SDS_PLATFORM_INFO_OFFSET, 71 &plat_info, 72 N1SDP_SDS_PLATFORM_INFO_SIZE, 73 SDS_ACCESS_MODE_NON_CACHED); 74 if (ret != SDS_OK) { 75 ERROR("Error getting platform info from SDS\n"); 76 panic(); 77 } 78 /* Validate plat_info SDS */ 79 if ((plat_info.local_ddr_size == 0) 80 || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) 81 || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) 82 || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) { 83 ERROR("platform info SDS is corrupted\n"); 84 panic(); 85 } 86 87 dmc_ecc_setup(plat_info.local_ddr_size); 88 arm_bl2_platform_setup(); 89 } 90