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 
mss_check_image_ready(volatile struct mss_pm_ctrl_block * mss_pm_crtl)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 
mss_image_load(uint32_t src_addr,uint32_t size,uintptr_t mss_regs)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  */
mss_ap_load_image(uintptr_t single_img,uint32_t image_size,uint32_t ap_idx)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 */
load_img_to_cm3(enum cm3_t cm3_type,uintptr_t single_img,uint32_t image_size)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  */
split_and_load_bl2_image(void * image)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 
scp_bootloader_transfer(void * image,unsigned int image_size)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