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