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