1 /* 2 * Copyright (C) 2018 Marvell International Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * https://spdx.org/licenses 6 */ 7 8 #include <assert.h> 9 10 #include <platform_def.h> 11 12 #include <arch_helpers.h> 13 #include <common/debug.h> 14 #include <drivers/delay_timer.h> 15 #include <mg_conf_cm3/mg_conf_cm3.h> 16 #include <lib/mmio.h> 17 18 #include <plat_pm_trace.h> 19 #include <mss_scp_bootloader.h> 20 #include <mss_ipc_drv.h> 21 #include <mss_mem.h> 22 #include <mss_scp_bl2_format.h> 23 24 #define MSS_DMA_SRCBR(base) (base + 0xC0) 25 #define MSS_DMA_DSTBR(base) (base + 0xC4) 26 #define MSS_DMA_CTRLR(base) (base + 0xC8) 27 #define MSS_M3_RSTCR(base) (base + 0xFC) 28 29 #define MSS_DMA_CTRLR_SIZE_OFFSET (0) 30 #define MSS_DMA_CTRLR_REQ_OFFSET (15) 31 #define MSS_DMA_CTRLR_REQ_SET (1) 32 #define MSS_DMA_CTRLR_ACK_OFFSET (12) 33 #define MSS_DMA_CTRLR_ACK_MASK (0x1) 34 #define MSS_DMA_CTRLR_ACK_READY (1) 35 #define MSS_M3_RSTCR_RST_OFFSET (0) 36 #define MSS_M3_RSTCR_RST_OFF (1) 37 38 #define MSS_DMA_TIMEOUT 1000 39 #define MSS_EXTERNAL_SPACE 0x50000000 40 #define MSS_EXTERNAL_ADDR_MASK 0xfffffff 41 42 #define DMA_SIZE 128 43 44 #define MSS_HANDSHAKE_TIMEOUT 50 45 46 static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl) 47 { 48 int timeout = MSS_HANDSHAKE_TIMEOUT; 49 50 /* Wait for SCP to signal it's ready */ 51 while ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) && 52 (timeout-- > 0)) 53 mdelay(1); 54 55 if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) 56 return -1; 57 58 mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT; 59 60 return 0; 61 } 62 63 static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs) 64 { 65 uint32_t i, loop_num, timeout; 66 67 /* Check if the img size is not bigger than ID-RAM size of MSS CM3 */ 68 if (size > MSS_IDRAM_SIZE) { 69 ERROR("image is too big to fit into MSS CM3 memory\n"); 70 return 1; 71 } 72 73 NOTICE("Loading MSS image from addr. 0x%x Size 0x%x to MSS at 0x%lx\n", 74 src_addr, size, mss_regs); 75 /* load image to MSS RAM using DMA */ 76 loop_num = (size / DMA_SIZE) + (((size & (DMA_SIZE - 1)) == 0) ? 0 : 1); 77 78 for (i = 0; i < loop_num; i++) { 79 /* write destination and source addresses */ 80 mmio_write_32(MSS_DMA_SRCBR(mss_regs), 81 MSS_EXTERNAL_SPACE | 82 ((src_addr & MSS_EXTERNAL_ADDR_MASK) + 83 (i * DMA_SIZE))); 84 mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE)); 85 86 dsb(); /* make sure DMA data is ready before triggering it */ 87 88 /* set the DMA control register */ 89 mmio_write_32(MSS_DMA_CTRLR(mss_regs), ((MSS_DMA_CTRLR_REQ_SET 90 << MSS_DMA_CTRLR_REQ_OFFSET) | 91 (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET))); 92 93 /* Poll DMA_ACK at MSS_DMACTLR until it is ready */ 94 timeout = MSS_DMA_TIMEOUT; 95 while (timeout) { 96 if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >> 97 MSS_DMA_CTRLR_ACK_OFFSET & MSS_DMA_CTRLR_ACK_MASK) 98 == MSS_DMA_CTRLR_ACK_READY) { 99 break; 100 } 101 102 udelay(50); 103 timeout--; 104 } 105 106 if (timeout == 0) { 107 ERROR("\nDMA failed to load MSS image\n"); 108 return 1; 109 } 110 } 111 112 bl2_plat_configure_mss_windows(mss_regs); 113 114 /* Release M3 from reset */ 115 mmio_write_32(MSS_M3_RSTCR(mss_regs), (MSS_M3_RSTCR_RST_OFF << 116 MSS_M3_RSTCR_RST_OFFSET)); 117 118 NOTICE("Done\n"); 119 120 return 0; 121 } 122 123 /* Load image to MSS AP and do PM related initialization 124 * Note that this routine is different than other CM3 loading routines, because 125 * firmware for AP is dedicated for PM and therefore some additional PM 126 * initialization is required 127 */ 128 static int mss_ap_load_image(uintptr_t single_img, 129 uint32_t image_size, uint32_t ap_idx) 130 { 131 volatile struct mss_pm_ctrl_block *mss_pm_crtl; 132 int ret; 133 134 /* TODO: add PM Control Info from platform */ 135 mss_pm_crtl = (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE; 136 mss_pm_crtl->ipc_version = MV_PM_FW_IPC_VERSION; 137 mss_pm_crtl->num_of_clusters = PLAT_MARVELL_CLUSTER_COUNT; 138 mss_pm_crtl->num_of_cores_per_cluster = 139 PLAT_MARVELL_CLUSTER_CORE_COUNT; 140 mss_pm_crtl->num_of_cores = PLAT_MARVELL_CLUSTER_COUNT * 141 PLAT_MARVELL_CLUSTER_CORE_COUNT; 142 mss_pm_crtl->pm_trace_ctrl_base_address = AP_MSS_ATF_CORE_CTRL_BASE; 143 mss_pm_crtl->pm_trace_info_base_address = AP_MSS_ATF_CORE_INFO_BASE; 144 mss_pm_crtl->pm_trace_info_core_size = AP_MSS_ATF_CORE_INFO_SIZE; 145 VERBOSE("MSS Control Block = 0x%x\n", MSS_SRAM_PM_CONTROL_BASE); 146 VERBOSE("mss_pm_crtl->ipc_version = 0x%x\n", 147 mss_pm_crtl->ipc_version); 148 VERBOSE("mss_pm_crtl->num_of_cores = 0x%x\n", 149 mss_pm_crtl->num_of_cores); 150 VERBOSE("mss_pm_crtl->num_of_clusters = 0x%x\n", 151 mss_pm_crtl->num_of_clusters); 152 VERBOSE("mss_pm_crtl->num_of_cores_per_cluster = 0x%x\n", 153 mss_pm_crtl->num_of_cores_per_cluster); 154 VERBOSE("mss_pm_crtl->pm_trace_ctrl_base_address = 0x%x\n", 155 mss_pm_crtl->pm_trace_ctrl_base_address); 156 VERBOSE("mss_pm_crtl->pm_trace_info_base_address = 0x%x\n", 157 mss_pm_crtl->pm_trace_info_base_address); 158 VERBOSE("mss_pm_crtl->pm_trace_info_core_size = 0x%x\n", 159 mss_pm_crtl->pm_trace_info_core_size); 160 161 /* TODO: add checksum to image */ 162 VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n"); 163 164 ret = mss_image_load(single_img, image_size, 165 bl2_plat_get_ap_mss_regs(ap_idx)); 166 if (ret != 0) { 167 ERROR("SCP Image load failed\n"); 168 return -1; 169 } 170 171 /* check that the image was loaded successfully */ 172 ret = mss_check_image_ready(mss_pm_crtl); 173 if (ret != 0) 174 NOTICE("SCP Image doesn't contain PM firmware\n"); 175 176 return 0; 177 } 178 179 /* Load CM3 image (single_img) to CM3 pointed by cm3_type */ 180 static int load_img_to_cm3(enum cm3_t cm3_type, 181 uintptr_t single_img, uint32_t image_size) 182 { 183 int ret, ap_idx, cp_index; 184 uint32_t ap_count = bl2_plat_get_ap_count(); 185 186 switch (cm3_type) { 187 case MSS_AP: 188 for (ap_idx = 0; ap_idx < ap_count; ap_idx++) { 189 NOTICE("Load image to AP%d MSS\n", ap_idx); 190 ret = mss_ap_load_image(single_img, image_size, ap_idx); 191 if (ret != 0) 192 return ret; 193 } 194 break; 195 case MSS_CP0: 196 case MSS_CP1: 197 case MSS_CP2: 198 case MSS_CP3: 199 /* MSS_AP = 0 200 * MSS_CP1 = 1 201 * . 202 * . 203 * MSS_CP3 = 4 204 * Actual CP index is MSS_CPX - 1 205 */ 206 cp_index = cm3_type - 1; 207 for (ap_idx = 0; ap_idx < ap_count; ap_idx++) { 208 /* Check if we should load this image 209 * according to number of CPs 210 */ 211 if (bl2_plat_get_cp_count(ap_idx) <= cp_index) { 212 NOTICE("Skipping MSS CP%d related image\n", 213 cp_index); 214 break; 215 } 216 217 NOTICE("Load image to CP%d MSS AP%d\n", 218 cp_index, ap_idx); 219 ret = mss_image_load(single_img, image_size, 220 bl2_plat_get_cp_mss_regs( 221 ap_idx, cp_index)); 222 if (ret != 0) { 223 ERROR("SCP Image load failed\n"); 224 return -1; 225 } 226 } 227 break; 228 case MG_CP0: 229 case MG_CP1: 230 case MG_CP2: 231 cp_index = cm3_type - MG_CP0; 232 if (bl2_plat_get_cp_count(0) <= cp_index) { 233 NOTICE("Skipping MG CP%d related image\n", 234 cp_index); 235 break; 236 } 237 NOTICE("Load image to CP%d MG\n", cp_index); 238 ret = mg_image_load(single_img, image_size, cp_index); 239 if (ret != 0) { 240 ERROR("SCP Image load failed\n"); 241 return -1; 242 } 243 break; 244 default: 245 ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type); 246 break; 247 } 248 249 return 0; 250 } 251 252 /* The Armada 8K has 5 service CPUs and Armada 7K has 3. Therefore it was 253 * required to provide a method for loading firmware to all of the service CPUs. 254 * To achieve that, the scp_bl2 image in fact is file containing up to 5 255 * concatenated firmwares and this routine splits concatenated image into single 256 * images dedicated for appropriate service CPU and then load them. 257 */ 258 static int split_and_load_bl2_image(void *image) 259 { 260 file_header_t *file_hdr; 261 img_header_t *img_hdr; 262 uintptr_t single_img; 263 int i; 264 265 file_hdr = (file_header_t *)image; 266 267 if (file_hdr->magic != FILE_MAGIC) { 268 ERROR("SCP_BL2 wrong img format\n"); 269 return -1; 270 } 271 272 if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) { 273 ERROR("SCP_BL2 concatenated image contains too many images\n"); 274 return -1; 275 } 276 277 img_hdr = (img_header_t *)((uintptr_t)image + sizeof(file_header_t)); 278 single_img = (uintptr_t)image + sizeof(file_header_t) + 279 sizeof(img_header_t) * file_hdr->nr_of_imgs; 280 281 NOTICE("SCP_BL2 contains %d concatenated images\n", 282 file_hdr->nr_of_imgs); 283 for (i = 0; i < file_hdr->nr_of_imgs; i++) { 284 285 /* Before loading make sanity check on header */ 286 if (img_hdr->version != HEADER_VERSION) { 287 ERROR("Wrong header, img corrupted exiting\n"); 288 return -1; 289 } 290 291 load_img_to_cm3(img_hdr->type, single_img, img_hdr->length); 292 293 /* Prepare offsets for next run */ 294 single_img += img_hdr->length; 295 img_hdr++; 296 } 297 298 return 0; 299 } 300 301 int scp_bootloader_transfer(void *image, unsigned int image_size) 302 { 303 #ifdef SCP_BL2_BASE 304 assert((uintptr_t) image == SCP_BL2_BASE); 305 #endif 306 307 VERBOSE("Concatenated img size %d\n", image_size); 308 309 if (image_size == 0) { 310 ERROR("SCP_BL2 image size can't be 0 (current size = 0x%x)\n", 311 image_size); 312 return -1; 313 } 314 315 if (split_and_load_bl2_image(image)) 316 return -1; 317 318 return 0; 319 } 320