1 /* 2 * Copyright (c) 2020-2021, 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/css_mhu_doorbell.h> 9 #include <drivers/arm/css/scmi.h> 10 #include <drivers/arm/css/sds.h> 11 #include <lib/cassert.h> 12 #include <lib/utils.h> 13 #include <plat/arm/common/plat_arm.h> 14 15 #include "morello_def.h" 16 #include <platform_def.h> 17 18 /* 19 * Platform information structure stored in SDS. 20 * This structure holds information about platform's DDR 21 * size which is an information about multichip setup 22 * - Local DDR size in bytes, DDR memory in master board 23 * - Remote DDR size in bytes, DDR memory in slave board 24 * - slave_count 25 * - multichip mode 26 */ 27 struct morello_plat_info { 28 uint64_t local_ddr_size; 29 uint64_t remote_ddr_size; 30 uint8_t slave_count; 31 bool multichip_mode; 32 } __packed; 33 34 /* Compile time assertion to ensure the size of structure is 18 bytes */ 35 CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE, 36 assert_invalid_plat_info_size); 37 /* 38 * BL33 image information structure stored in SDS. 39 * This structure holds the source & destination addresses and 40 * the size of the BL33 image which will be loaded by BL31. 41 */ 42 struct morello_bl33_info { 43 uint32_t bl33_src_addr; 44 uint32_t bl33_dst_addr; 45 uint32_t bl33_size; 46 }; 47 48 static scmi_channel_plat_info_t morello_scmi_plat_info = { 49 .scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE, 50 .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, 51 .db_preserve_mask = 0xfffffffe, 52 .db_modify_mask = 0x1, 53 .ring_doorbell = &mhu_ring_doorbell 54 }; 55 56 scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) 57 { 58 return &morello_scmi_plat_info; 59 } 60 61 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 62 { 63 return css_scmi_override_pm_ops(ops); 64 } 65 66 #ifdef TARGET_PLATFORM_SOC 67 /* 68 * Morello platform supports RDIMMs with ECC capability. To use the ECC 69 * capability, the entire DDR memory space has to be zeroed out before 70 * enabling the ECC bits in DMC-Bing. Zeroing out several gigabytes of 71 * memory from SCP is quite time consuming so the following function 72 * is added to zero out the DDR memory from application processor which is 73 * much faster compared to SCP. BL33 binary cannot be copied to DDR memory 74 * before enabling ECC so copy_bl33 function is added to copy BL33 binary 75 * from IOFPGA-DDR3 memory to main DDR4 memory. 76 */ 77 78 static void dmc_ecc_setup(struct morello_plat_info *plat_info) 79 { 80 uint64_t dram2_size; 81 uint32_t val; 82 83 INFO("Total DIMM size: %uGB\n", 84 (uint32_t)(plat_info->local_ddr_size / 0x40000000)); 85 86 assert(plat_info->local_ddr_size > ARM_DRAM1_SIZE); 87 dram2_size = plat_info->local_ddr_size - ARM_DRAM1_SIZE; 88 89 VERBOSE("Zeroing DDR memories\n"); 90 zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); 91 flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); 92 zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); 93 flush_dcache_range(ARM_DRAM2_BASE, dram2_size); 94 95 /* Clear previous ECC errors while zeroing out the memory */ 96 val = mmio_read_32(MORELLO_DMC0_ERR2STATUS_REG); 97 mmio_write_32(MORELLO_DMC0_ERR2STATUS_REG, val); 98 99 val = mmio_read_32(MORELLO_DMC1_ERR2STATUS_REG); 100 mmio_write_32(MORELLO_DMC1_ERR2STATUS_REG, val); 101 102 /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ 103 mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); 104 mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); 105 106 while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & 107 MORELLO_DMC_MEMC_STATUS_MASK) != 108 MORELLO_DMC_MEMC_CMD_CONFIG) { 109 continue; 110 } 111 112 while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & 113 MORELLO_DMC_MEMC_STATUS_MASK) != 114 MORELLO_DMC_MEMC_CMD_CONFIG) { 115 continue; 116 } 117 118 INFO("Enabling ECC on DMCs\n"); 119 /* Enable ECC in DMCs */ 120 mmio_setbits_32(MORELLO_DMC0_ERR0CTLR0_REG, 121 MORELLO_DMC_ERR0CTLR0_ECC_EN); 122 mmio_setbits_32(MORELLO_DMC1_ERR0CTLR0_REG, 123 MORELLO_DMC_ERR0CTLR0_ECC_EN); 124 125 /* Set DMCs to READY state */ 126 mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); 127 mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); 128 129 while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & 130 MORELLO_DMC_MEMC_STATUS_MASK) != 131 MORELLO_DMC_MEMC_CMD_READY) { 132 continue; 133 } 134 135 while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & 136 MORELLO_DMC_MEMC_STATUS_MASK) != 137 MORELLO_DMC_MEMC_CMD_READY) { 138 continue; 139 } 140 } 141 #endif 142 143 static void copy_bl33(uint32_t src, uint32_t dst, uint32_t size) 144 { 145 unsigned int i; 146 147 INFO("Copying BL33 to DDR memory...\n"); 148 for (i = 0U; i < size; (i = i + 8U)) 149 mmio_write_64((dst + i), mmio_read_64(src + i)); 150 151 for (i = 0U; i < size; (i = i + 8U)) { 152 if (mmio_read_64(src + i) != mmio_read_64(dst + i)) { 153 ERROR("Copy failed!\n"); 154 panic(); 155 } 156 } 157 INFO("done\n"); 158 } 159 160 void bl31_platform_setup(void) 161 { 162 int ret; 163 struct morello_plat_info plat_info; 164 struct morello_bl33_info bl33_info; 165 struct morello_plat_info *copy_dest; 166 167 ret = sds_init(); 168 if (ret != SDS_OK) { 169 ERROR("SDS initialization failed. ret:%d\n", ret); 170 panic(); 171 } 172 173 ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID, 174 MORELLO_SDS_PLATFORM_INFO_OFFSET, 175 &plat_info, 176 MORELLO_SDS_PLATFORM_INFO_SIZE, 177 SDS_ACCESS_MODE_NON_CACHED); 178 if (ret != SDS_OK) { 179 ERROR("Error getting platform info from SDS. ret:%d\n", ret); 180 panic(); 181 } 182 183 /* Validate plat_info SDS */ 184 if ((plat_info.local_ddr_size == 0U) 185 || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) 186 || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) 187 || (plat_info.slave_count > MORELLO_MAX_SLAVE_COUNT)) { 188 ERROR("platform info SDS is corrupted\n"); 189 panic(); 190 } 191 192 arm_bl31_platform_setup(); 193 194 #ifdef TARGET_PLATFORM_SOC 195 dmc_ecc_setup(&plat_info); 196 #endif 197 198 ret = sds_struct_read(MORELLO_SDS_BL33_INFO_STRUCT_ID, 199 MORELLO_SDS_BL33_INFO_OFFSET, 200 &bl33_info, 201 MORELLO_SDS_BL33_INFO_SIZE, 202 SDS_ACCESS_MODE_NON_CACHED); 203 if (ret != SDS_OK) { 204 ERROR("Error getting BL33 info from SDS. ret:%d\n", ret); 205 panic(); 206 } 207 copy_bl33(bl33_info.bl33_src_addr, 208 bl33_info.bl33_dst_addr, 209 bl33_info.bl33_size); 210 /* 211 * Pass platform information to BL33. This method is followed as 212 * currently there is no BL1/BL2 involved in boot flow of MORELLO. 213 * When TBBR is implemented for MORELLO, this method should be removed 214 * and platform information should be passed to BL33 using NT_FW_CONFIG 215 * passing mechanism. 216 */ 217 copy_dest = (struct morello_plat_info *)MORELLO_PLATFORM_INFO_BASE; 218 *copy_dest = plat_info; 219 } 220