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