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_defs.h>
23 #include <mss_scp_bl2_format.h>
24 
25 #define MSS_DMA_TIMEOUT			1000
26 #define MSS_EXTERNAL_SPACE		0x50000000
27 #define MSS_EXTERNAL_ADDR_MASK		0xfffffff
28 #define MSS_INTERNAL_SPACE		0x40000000
29 #define MSS_INTERNAL_ADDR_MASK		0x00ffffff
30 
31 #define DMA_SIZE			128
32 
33 #define MSS_HANDSHAKE_TIMEOUT		50
34 
mss_check_image_ready(volatile struct mss_pm_ctrl_block * mss_pm_crtl)35 static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
36 {
37 	int timeout = MSS_HANDSHAKE_TIMEOUT;
38 
39 	/* Wait for SCP to signal it's ready */
40 	while ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) &&
41 						(timeout-- > 0))
42 		mdelay(1);
43 
44 	if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT)
45 		return -1;
46 
47 	mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT;
48 
49 	return 0;
50 }
51 
mss_iram_dma_load(uint32_t src_addr,uint32_t size,uintptr_t mss_regs)52 static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
53 			     uintptr_t mss_regs)
54 {
55 	uint32_t i, loop_num, timeout;
56 
57 	/* load image to MSS RAM using DMA */
58 	loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
59 	for (i = 0; i < loop_num; i++) {
60 		/* write source address */
61 		mmio_write_32(MSS_DMA_SRCBR(mss_regs),
62 			      src_addr + (i * DMA_SIZE));
63 		/* write destination address */
64 		mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
65 		/* make sure DMA data is ready before triggering it */
66 		dsb();
67 		/* set the DMA control register */
68 		mmio_write_32(MSS_DMA_CTRLR(mss_regs),
69 			      ((MSS_DMA_CTRLR_REQ_SET <<
70 				MSS_DMA_CTRLR_REQ_OFFSET) |
71 			      (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
72 		/* Poll DMA_ACK at MSS_DMACTLR until it is ready */
73 		timeout = MSS_DMA_TIMEOUT;
74 		while (timeout > 0U) {
75 			if (((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
76 					  MSS_DMA_CTRLR_ACK_OFFSET) &
77 					  MSS_DMA_CTRLR_ACK_MASK)
78 					  == MSS_DMA_CTRLR_ACK_READY) {
79 				break;
80 			}
81 			udelay(50);
82 			timeout--;
83 		}
84 		if (timeout == 0) {
85 			ERROR("\nMSS DMA failed (timeout)\n");
86 			return 1;
87 		}
88 	}
89 	return 0;
90 }
91 
mss_image_load(uint32_t src_addr,uint32_t size,uintptr_t mss_regs,uintptr_t sram)92 static int mss_image_load(uint32_t src_addr, uint32_t size,
93 			  uintptr_t mss_regs, uintptr_t sram)
94 {
95 	uint32_t chunks = 1; /* !sram case */
96 	uint32_t chunk_num;
97 	int ret;
98 
99 	/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
100 	if (size > MSS_IDRAM_SIZE) {
101 		ERROR("image is too big to fit into MSS CM3 memory\n");
102 		return 1;
103 	}
104 
105 	/* The CPx MSS DMA cannot access DRAM directly in secure boot mode
106 	 * Copy the MSS FW image to MSS SRAM by the CPU first, then run
107 	 * MSS DMA for SRAM to IRAM copy
108 	 */
109 	if (sram != 0) {
110 		chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
111 	}
112 
113 	NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
114 	       sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
115 	for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
116 		size_t chunk_size = size;
117 		uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
118 				   (src_addr & MSS_EXTERNAL_ADDR_MASK);
119 
120 		if (sram != 0) {
121 			uintptr_t chunk_source =
122 				  src_addr + MSS_SRAM_SIZE * chunk_num;
123 
124 			if (chunk_num != (size / MSS_SRAM_SIZE)) {
125 				chunk_size = MSS_SRAM_SIZE;
126 			} else {
127 				chunk_size =  size % MSS_SRAM_SIZE;
128 			}
129 
130 			if (chunk_size == 0) {
131 				break;
132 			}
133 
134 			VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
135 				chunk_num, sram, chunk_source, chunk_size);
136 			memcpy((void *)sram, (void *)chunk_source, chunk_size);
137 			dsb();
138 			img_src = MSS_INTERNAL_SPACE |
139 				  (sram & MSS_INTERNAL_ADDR_MASK);
140 		}
141 
142 		ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
143 		if (ret != 0) {
144 			ERROR("MSS FW chunk %d load failed\n", chunk_num);
145 			return ret;
146 		}
147 	}
148 
149 	bl2_plat_configure_mss_windows(mss_regs);
150 
151 	if (sram != 0) {
152 		/* Wipe the MSS SRAM after using it as copy buffer */
153 		memset((void *)sram, 0, MSS_SRAM_SIZE);
154 		NOTICE("CP MSS startup is postponed\n");
155 		/* FW loaded, but CPU startup postponed until final CP setup */
156 		mmio_write_32(sram, MSS_FW_READY_MAGIC);
157 		dsb();
158 	} else {
159 		/* Release M3 from reset */
160 		mmio_write_32(MSS_M3_RSTCR(mss_regs),
161 			      (MSS_M3_RSTCR_RST_OFF <<
162 			       MSS_M3_RSTCR_RST_OFFSET));
163 	}
164 
165 	NOTICE("Done\n");
166 
167 	return 0;
168 }
169 
170 /* Load image to MSS AP and do PM related initialization
171  * Note that this routine is different than other CM3 loading routines, because
172  * firmware for AP is dedicated for PM and therefore some additional PM
173  * initialization is required
174  */
mss_ap_load_image(uintptr_t single_img,uint32_t image_size,uint32_t ap_idx)175 static int mss_ap_load_image(uintptr_t single_img,
176 			     uint32_t image_size, uint32_t ap_idx)
177 {
178 	volatile struct mss_pm_ctrl_block *mss_pm_crtl;
179 	int ret;
180 
181 	/* TODO: add PM Control Info from platform */
182 	mss_pm_crtl = (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE;
183 	mss_pm_crtl->ipc_version                = MV_PM_FW_IPC_VERSION;
184 	mss_pm_crtl->num_of_clusters            = PLAT_MARVELL_CLUSTER_COUNT;
185 	mss_pm_crtl->num_of_cores_per_cluster   =
186 						PLAT_MARVELL_CLUSTER_CORE_COUNT;
187 	mss_pm_crtl->num_of_cores               = PLAT_MARVELL_CLUSTER_COUNT *
188 						PLAT_MARVELL_CLUSTER_CORE_COUNT;
189 	mss_pm_crtl->pm_trace_ctrl_base_address = AP_MSS_ATF_CORE_CTRL_BASE;
190 	mss_pm_crtl->pm_trace_info_base_address = AP_MSS_ATF_CORE_INFO_BASE;
191 	mss_pm_crtl->pm_trace_info_core_size    = AP_MSS_ATF_CORE_INFO_SIZE;
192 	VERBOSE("MSS Control Block = 0x%x\n", MSS_SRAM_PM_CONTROL_BASE);
193 	VERBOSE("mss_pm_crtl->ipc_version                = 0x%x\n",
194 		mss_pm_crtl->ipc_version);
195 	VERBOSE("mss_pm_crtl->num_of_cores               = 0x%x\n",
196 		mss_pm_crtl->num_of_cores);
197 	VERBOSE("mss_pm_crtl->num_of_clusters            = 0x%x\n",
198 		mss_pm_crtl->num_of_clusters);
199 	VERBOSE("mss_pm_crtl->num_of_cores_per_cluster   = 0x%x\n",
200 		mss_pm_crtl->num_of_cores_per_cluster);
201 	VERBOSE("mss_pm_crtl->pm_trace_ctrl_base_address = 0x%x\n",
202 		mss_pm_crtl->pm_trace_ctrl_base_address);
203 	VERBOSE("mss_pm_crtl->pm_trace_info_base_address = 0x%x\n",
204 		mss_pm_crtl->pm_trace_info_base_address);
205 	VERBOSE("mss_pm_crtl->pm_trace_info_core_size    = 0x%x\n",
206 		mss_pm_crtl->pm_trace_info_core_size);
207 
208 	/* TODO: add checksum to image */
209 	VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
210 
211 	ret = mss_image_load(single_img, image_size,
212 			     bl2_plat_get_ap_mss_regs(ap_idx), 0);
213 	if (ret != 0) {
214 		ERROR("SCP Image load failed\n");
215 		return -1;
216 	}
217 
218 	/* check that the image was loaded successfully */
219 	ret = mss_check_image_ready(mss_pm_crtl);
220 	if (ret != 0)
221 		NOTICE("SCP Image doesn't contain PM firmware\n");
222 
223 	return 0;
224 }
225 
226 /* Load CM3 image (single_img) to CM3 pointed by cm3_type */
load_img_to_cm3(enum cm3_t cm3_type,uintptr_t single_img,uint32_t image_size)227 static int load_img_to_cm3(enum cm3_t cm3_type,
228 			   uintptr_t single_img, uint32_t image_size)
229 {
230 	int ret, ap_idx, cp_index;
231 	uint32_t ap_count = bl2_plat_get_ap_count();
232 
233 	switch (cm3_type) {
234 	case MSS_AP:
235 		for (ap_idx = 0; ap_idx < ap_count; ap_idx++) {
236 			NOTICE("Load image to AP%d MSS\n", ap_idx);
237 			ret = mss_ap_load_image(single_img, image_size, ap_idx);
238 			if (ret != 0)
239 				return ret;
240 		}
241 		break;
242 	case MSS_CP0:
243 	case MSS_CP1:
244 	case MSS_CP2:
245 	case MSS_CP3:
246 		/* MSS_AP = 0
247 		 * MSS_CP1 = 1
248 		 * .
249 		 * .
250 		 * MSS_CP3 = 4
251 		 * Actual CP index is MSS_CPX - 1
252 		 */
253 		cp_index = cm3_type - 1;
254 		for (ap_idx = 0; ap_idx < ap_count; ap_idx++) {
255 			/* Check if we should load this image
256 			 * according to number of CPs
257 			 */
258 			if (bl2_plat_get_cp_count(ap_idx) <= cp_index) {
259 				NOTICE("Skipping MSS CP%d related image\n",
260 				       cp_index);
261 				break;
262 			}
263 
264 			NOTICE("Load image to CP%d MSS AP%d\n",
265 			       cp_index, ap_idx);
266 			ret = mss_image_load(single_img, image_size,
267 					     bl2_plat_get_cp_mss_regs(
268 						     ap_idx, cp_index),
269 					     bl2_plat_get_cp_mss_sram(
270 						     ap_idx, cp_index));
271 			if (ret != 0) {
272 				ERROR("SCP Image load failed\n");
273 				return -1;
274 			}
275 		}
276 		break;
277 	case MG_CP0:
278 	case MG_CP1:
279 	case MG_CP2:
280 		cp_index = cm3_type - MG_CP0;
281 		if (bl2_plat_get_cp_count(0) <= cp_index) {
282 			NOTICE("Skipping MG CP%d related image\n",
283 			       cp_index);
284 			break;
285 		}
286 		NOTICE("Load image to CP%d MG\n", cp_index);
287 		ret = mg_image_load(single_img, image_size, cp_index);
288 		if (ret != 0) {
289 			ERROR("SCP Image load failed\n");
290 			return -1;
291 		}
292 		break;
293 	default:
294 		ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type);
295 		break;
296 	}
297 
298 	return 0;
299 }
300 
301 /* The Armada 8K has 5 service CPUs and Armada 7K has 3. Therefore it was
302  * required to provide a method for loading firmware to all of the service CPUs.
303  * To achieve that, the scp_bl2 image in fact is file containing up to 5
304  * concatenated firmwares and this routine splits concatenated image into single
305  * images dedicated for appropriate service CPU and then load them.
306  */
split_and_load_bl2_image(void * image)307 static int split_and_load_bl2_image(void *image)
308 {
309 	file_header_t *file_hdr;
310 	img_header_t *img_hdr;
311 	uintptr_t single_img;
312 	int i;
313 
314 	file_hdr = (file_header_t *)image;
315 
316 	if (file_hdr->magic != FILE_MAGIC) {
317 		ERROR("SCP_BL2 wrong img format\n");
318 		return -1;
319 	}
320 
321 	if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) {
322 		ERROR("SCP_BL2 concatenated image contains too many images\n");
323 		return -1;
324 	}
325 
326 	img_hdr = (img_header_t *)((uintptr_t)image + sizeof(file_header_t));
327 	single_img = (uintptr_t)image + sizeof(file_header_t) +
328 				    sizeof(img_header_t) * file_hdr->nr_of_imgs;
329 
330 	NOTICE("SCP_BL2 contains %d concatenated images\n",
331 							  file_hdr->nr_of_imgs);
332 	for (i = 0; i < file_hdr->nr_of_imgs; i++) {
333 
334 		/* Before loading make sanity check on header */
335 		if (img_hdr->version != HEADER_VERSION) {
336 			ERROR("Wrong header, img corrupted exiting\n");
337 			return -1;
338 		}
339 
340 		load_img_to_cm3(img_hdr->type, single_img, img_hdr->length);
341 
342 		/* Prepare offsets for next run */
343 		single_img += img_hdr->length;
344 		img_hdr++;
345 	}
346 
347 	return 0;
348 }
349 
scp_bootloader_transfer(void * image,unsigned int image_size)350 int scp_bootloader_transfer(void *image, unsigned int image_size)
351 {
352 #ifdef SCP_BL2_BASE
353 	assert((uintptr_t) image == SCP_BL2_BASE);
354 #endif
355 
356 	VERBOSE("Concatenated img size %d\n", image_size);
357 
358 	if (image_size == 0) {
359 		ERROR("SCP_BL2 image size can't be 0 (current size = 0x%x)\n",
360 								    image_size);
361 		return -1;
362 	}
363 
364 	if (split_and_load_bl2_image(image))
365 		return -1;
366 
367 	return 0;
368 }
369