1 /* 2 * Copyright (c) 2021-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 #include <plat/arm/common/plat_arm.h> 12 13 #include "morello_def.h" 14 #include <platform_def.h> 15 16 #ifdef TARGET_PLATFORM_FVP 17 /* 18 * Platform information structure stored in SDS. 19 * This structure holds information about platform's DDR 20 * size 21 * - Local DDR size in bytes, DDR memory in main board 22 */ 23 struct morello_plat_info { 24 uint64_t local_ddr_size; 25 } __packed; 26 #else 27 /* 28 * Platform information structure stored in SDS. 29 * This structure holds information about platform's DDR 30 * size which is an information about multichip setup 31 * - Local DDR size in bytes, DDR memory in main board 32 * - Remote DDR size in bytes, DDR memory in remote board 33 * - remote_chip_count 34 * - multichip mode 35 * - scc configuration 36 */ 37 struct morello_plat_info { 38 uint64_t local_ddr_size; 39 uint64_t remote_ddr_size; 40 uint8_t remote_chip_count; 41 bool multichip_mode; 42 uint32_t scc_config; 43 } __packed; 44 #endif 45 46 /* Compile time assertion to ensure the size of structure is 18 bytes */ 47 CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE, 48 assert_invalid_plat_info_size); 49 50 #ifdef TARGET_PLATFORM_SOC 51 /* 52 * Morello platform supports RDIMMs with ECC capability. To use the ECC 53 * capability, the entire DDR memory space has to be zeroed out before 54 * enabling the ECC bits in DMC-Bing. Zeroing out several gigabytes of 55 * memory from SCP is quite time consuming so the following function 56 * is added to zero out the DDR memory from application processor which is 57 * much faster compared to SCP. 58 */ 59 60 static void dmc_ecc_setup(struct morello_plat_info *plat_info) 61 { 62 uint64_t dram2_size; 63 uint32_t val; 64 uint64_t tag_mem_base; 65 uint64_t usable_mem_size; 66 67 INFO("Total DIMM size: %uGB\n", 68 (uint32_t)(plat_info->local_ddr_size / 0x40000000)); 69 70 assert(plat_info->local_ddr_size > ARM_DRAM1_SIZE); 71 dram2_size = plat_info->local_ddr_size - ARM_DRAM1_SIZE; 72 73 INFO("Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF\n"); 74 zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); 75 flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); 76 77 INFO("Zeroing DDR memory range 0x%llx - 0x%llx\n", 78 ARM_DRAM2_BASE, ARM_DRAM2_BASE + dram2_size); 79 zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); 80 flush_dcache_range(ARM_DRAM2_BASE, dram2_size); 81 82 /* Clear previous ECC errors while zeroing out the memory */ 83 val = mmio_read_32(MORELLO_DMC0_ERR2STATUS_REG); 84 mmio_write_32(MORELLO_DMC0_ERR2STATUS_REG, val); 85 86 val = mmio_read_32(MORELLO_DMC1_ERR2STATUS_REG); 87 mmio_write_32(MORELLO_DMC1_ERR2STATUS_REG, val); 88 89 /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ 90 mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); 91 mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); 92 93 while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & 94 MORELLO_DMC_MEMC_STATUS_MASK) != 95 MORELLO_DMC_MEMC_CMD_CONFIG) { 96 continue; 97 } 98 99 while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & 100 MORELLO_DMC_MEMC_STATUS_MASK) != 101 MORELLO_DMC_MEMC_CMD_CONFIG) { 102 continue; 103 } 104 105 /* Configure Bing client/server mode based on SCC configuration */ 106 if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) { 107 INFO("Configuring DMC Bing in client mode\n"); 108 usable_mem_size = plat_info->local_ddr_size - 109 (plat_info->local_ddr_size / 128ULL); 110 111 /* Linear DDR address */ 112 tag_mem_base = usable_mem_size; 113 tag_mem_base = tag_mem_base / 4; 114 115 /* Reverse translation */ 116 if (tag_mem_base < ARM_DRAM1_BASE) { 117 tag_mem_base += ARM_DRAM1_BASE; 118 } else { 119 tag_mem_base = tag_mem_base - ARM_DRAM1_BASE + 120 ARM_DRAM2_BASE; 121 } 122 123 mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x1); 124 mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x1); 125 mmio_write_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x1); 126 mmio_write_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x1); 127 128 if (plat_info->scc_config & MORELLO_SCC_C1_TAG_CACHE_EN_MASK) { 129 mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x2); 130 mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x2); 131 INFO("C1 Tag Cache Enabled\n"); 132 } 133 134 if (plat_info->scc_config & MORELLO_SCC_C2_TAG_CACHE_EN_MASK) { 135 mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x4); 136 mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x4); 137 INFO("C2 Tag Cache Enabled\n"); 138 } 139 140 mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL, 141 (uint32_t)tag_mem_base); 142 mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL, 143 (uint32_t)tag_mem_base); 144 mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL2, 145 (uint32_t)(tag_mem_base >> 32)); 146 mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL2, 147 (uint32_t)(tag_mem_base >> 32)); 148 149 mmio_setbits_32(MORELLO_DMC0_MEM_ACCESS_CTL, 150 MORELLO_DMC_MEM_ACCESS_DIS); 151 mmio_setbits_32(MORELLO_DMC1_MEM_ACCESS_CTL, 152 MORELLO_DMC_MEM_ACCESS_DIS); 153 154 INFO("Tag base set to 0x%lx\n", tag_mem_base); 155 plat_info->local_ddr_size = usable_mem_size; 156 } else { 157 INFO("Configuring DMC Bing in server mode\n"); 158 mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x0); 159 mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x0); 160 } 161 162 INFO("Enabling ECC on DMCs\n"); 163 /* Enable ECC in DMCs */ 164 mmio_setbits_32(MORELLO_DMC0_ERR0CTLR0_REG, 165 MORELLO_DMC_ERR0CTLR0_ECC_EN); 166 mmio_setbits_32(MORELLO_DMC1_ERR0CTLR0_REG, 167 MORELLO_DMC_ERR0CTLR0_ECC_EN); 168 169 /* Set DMCs to READY state */ 170 mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); 171 mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); 172 173 while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & 174 MORELLO_DMC_MEMC_STATUS_MASK) != 175 MORELLO_DMC_MEMC_CMD_READY) { 176 continue; 177 } 178 179 while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & 180 MORELLO_DMC_MEMC_STATUS_MASK) != 181 MORELLO_DMC_MEMC_CMD_READY) { 182 continue; 183 } 184 } 185 #endif 186 187 void bl2_platform_setup(void) 188 { 189 int ret; 190 struct morello_plat_info plat_info; 191 192 ret = sds_init(); 193 if (ret != SDS_OK) { 194 ERROR("SDS initialization failed. ret:%d\n", ret); 195 panic(); 196 } 197 198 ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID, 199 MORELLO_SDS_PLATFORM_INFO_OFFSET, 200 &plat_info, 201 MORELLO_SDS_PLATFORM_INFO_SIZE, 202 SDS_ACCESS_MODE_NON_CACHED); 203 if (ret != SDS_OK) { 204 ERROR("Error getting platform info from SDS. ret:%d\n", ret); 205 panic(); 206 } 207 208 /* Validate plat_info SDS */ 209 #ifdef TARGET_PLATFORM_FVP 210 if (plat_info.local_ddr_size == 0U) { 211 #else 212 if ((plat_info.local_ddr_size == 0U) 213 || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) 214 || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) 215 || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT) 216 ) { 217 #endif 218 ERROR("platform info SDS is corrupted\n"); 219 panic(); 220 } 221 222 #ifdef TARGET_PLATFORM_SOC 223 dmc_ecc_setup(&plat_info); 224 #endif 225 arm_bl2_platform_setup(); 226 } 227