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