blob: 3f5e48607d30af38212e705e6b9839b678271c6c [file] [log] [blame]
Haojian Zhuang934ae712017-05-24 08:47:49 +08001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <bl_common.h>
10#include <console.h>
11#include <debug.h>
Victor Chong2d9a42d2017-08-17 15:21:10 +090012#include <desc_image_load.h>
Haojian Zhuang934ae712017-05-24 08:47:49 +080013#include <dw_mmc.h>
14#include <emmc.h>
15#include <errno.h>
16#include <hi6220.h>
17#include <hisi_mcu.h>
18#include <hisi_sram_map.h>
19#include <mmio.h>
Victor Chong7d787f52017-08-16 13:53:56 +090020#if LOAD_IMAGE_V2
21#ifdef SPD_opteed
22#include <optee_utils.h>
23#endif
24#endif
Haojian Zhuang934ae712017-05-24 08:47:49 +080025#include <platform_def.h>
26#include <sp804_delay_timer.h>
27#include <string.h>
28
29#include "hikey_def.h"
30#include "hikey_private.h"
31
32/*
33 * The next 2 constants identify the extents of the code & RO data region.
34 * These addresses are used by the MMU setup code and therefore they must be
35 * page-aligned. It is the responsibility of the linker script to ensure that
36 * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
37 */
38#define BL2_RO_BASE (unsigned long)(&__RO_START__)
39#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
40
41/*
42 * The next 2 constants identify the extents of the coherent memory region.
43 * These addresses are used by the MMU setup code and therefore they must be
44 * page-aligned. It is the responsibility of the linker script to ensure that
45 * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
46 * page-aligned addresses.
47 */
48#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
49#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
50
51static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
52
Victor Chong2d9a42d2017-08-17 15:21:10 +090053#if !LOAD_IMAGE_V2
54
55/*******************************************************************************
56 * This structure represents the superset of information that is passed to
57 * BL31, e.g. while passing control to it from BL2, bl31_params
58 * and other platform specific params
59 ******************************************************************************/
Haojian Zhuang934ae712017-05-24 08:47:49 +080060typedef struct bl2_to_bl31_params_mem {
61 bl31_params_t bl31_params;
62 image_info_t bl31_image_info;
63 image_info_t bl32_image_info;
64 image_info_t bl33_image_info;
65 entry_point_info_t bl33_ep_info;
66 entry_point_info_t bl32_ep_info;
67 entry_point_info_t bl31_ep_info;
68} bl2_to_bl31_params_mem_t;
69
70static bl2_to_bl31_params_mem_t bl31_params_mem;
71
72meminfo_t *bl2_plat_sec_mem_layout(void)
73{
74 return &bl2_tzram_layout;
75}
76
77void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)
78{
79 scp_bl2_meminfo->total_base = SCP_BL2_BASE;
80 scp_bl2_meminfo->total_size = SCP_BL2_SIZE;
81 scp_bl2_meminfo->free_base = SCP_BL2_BASE;
82 scp_bl2_meminfo->free_size = SCP_BL2_SIZE;
83}
Victor Chong2d9a42d2017-08-17 15:21:10 +090084#endif /* LOAD_IMAGE_V2 */
Haojian Zhuang934ae712017-05-24 08:47:49 +080085
Victor Chong2d9a42d2017-08-17 15:21:10 +090086/*******************************************************************************
87 * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
88 * Return 0 on success, -1 otherwise.
89 ******************************************************************************/
90#if LOAD_IMAGE_V2
91int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
92#else
Haojian Zhuang934ae712017-05-24 08:47:49 +080093int bl2_plat_handle_scp_bl2(struct image_info *scp_bl2_image_info)
Victor Chong2d9a42d2017-08-17 15:21:10 +090094#endif
Haojian Zhuang934ae712017-05-24 08:47:49 +080095{
96 /* Enable MCU SRAM */
97 hisi_mcu_enable_sram();
98
99 /* Load MCU binary into SRAM */
100 hisi_mcu_load_image(scp_bl2_image_info->image_base,
101 scp_bl2_image_info->image_size);
102 /* Let MCU running */
103 hisi_mcu_start_run();
104
105 INFO("%s: MCU PC is at 0x%x\n",
106 __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2));
107 INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n",
108 __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4));
109 return 0;
110}
111
Victor Chong2d9a42d2017-08-17 15:21:10 +0900112/*******************************************************************************
113 * Gets SPSR for BL32 entry
114 ******************************************************************************/
115uint32_t hikey_get_spsr_for_bl32_entry(void)
116{
117 /*
118 * The Secure Payload Dispatcher service is responsible for
119 * setting the SPSR prior to entry into the BL3-2 image.
120 */
121 return 0;
122}
123
124/*******************************************************************************
125 * Gets SPSR for BL33 entry
126 ******************************************************************************/
127#ifndef AARCH32
128uint32_t hikey_get_spsr_for_bl33_entry(void)
129{
130 unsigned int mode;
131 uint32_t spsr;
132
133 /* Figure out what mode we enter the non-secure world in */
134 mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1;
135
136 /*
137 * TODO: Consider the possibility of specifying the SPSR in
138 * the FIP ToC and allowing the platform to have a say as
139 * well.
140 */
141 spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
142 return spsr;
143}
144#else
145uint32_t hikey_get_spsr_for_bl33_entry(void)
146{
147 unsigned int hyp_status, mode, spsr;
148
149 hyp_status = GET_VIRT_EXT(read_id_pfr1());
150
151 mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
152
153 /*
154 * TODO: Consider the possibility of specifying the SPSR in
155 * the FIP ToC and allowing the platform to have a say as
156 * well.
157 */
158 spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
159 SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
160 return spsr;
161}
162#endif /* AARCH32 */
163
164#if LOAD_IMAGE_V2
165int hikey_bl2_handle_post_image_load(unsigned int image_id)
166{
167 int err = 0;
168 bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
Victor Chong7d787f52017-08-16 13:53:56 +0900169#ifdef SPD_opteed
170 bl_mem_params_node_t *pager_mem_params = NULL;
171 bl_mem_params_node_t *paged_mem_params = NULL;
172#endif
Victor Chong2d9a42d2017-08-17 15:21:10 +0900173 assert(bl_mem_params);
174
175 switch (image_id) {
176#ifdef AARCH64
177 case BL32_IMAGE_ID:
Victor Chong7d787f52017-08-16 13:53:56 +0900178#ifdef SPD_opteed
179 pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
180 assert(pager_mem_params);
181
182 paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
183 assert(paged_mem_params);
184
185 err = parse_optee_header(&bl_mem_params->ep_info,
186 &pager_mem_params->image_info,
187 &paged_mem_params->image_info);
188 if (err != 0) {
189 WARN("OPTEE header parse error.\n");
190 }
191#endif
Victor Chong2d9a42d2017-08-17 15:21:10 +0900192 bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry();
193 break;
194#endif
195
196 case BL33_IMAGE_ID:
197 /* BL33 expects to receive the primary CPU MPID (through r0) */
198 bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
199 bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry();
200 break;
201
202#ifdef SCP_BL2_BASE
203 case SCP_BL2_IMAGE_ID:
204 /* The subsequent handling of SCP_BL2 is platform specific */
205 err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info);
206 if (err) {
207 WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
208 }
209 break;
210#endif
211 }
212
213 return err;
214}
215
216/*******************************************************************************
217 * This function can be used by the platforms to update/use image
218 * information for given `image_id`.
219 ******************************************************************************/
220int bl2_plat_handle_post_image_load(unsigned int image_id)
221{
222 return hikey_bl2_handle_post_image_load(image_id);
223}
224
225#else /* LOAD_IMAGE_V2 */
226
Haojian Zhuang934ae712017-05-24 08:47:49 +0800227bl31_params_t *bl2_plat_get_bl31_params(void)
228{
229 bl31_params_t *bl2_to_bl31_params = NULL;
230
231 /*
232 * Initialise the memory for all the arguments that needs to
233 * be passed to BL3-1
234 */
235 memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
236
237 /* Assign memory for TF related information */
238 bl2_to_bl31_params = &bl31_params_mem.bl31_params;
239 SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
240
241 /* Fill BL3-1 related information */
242 bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
243 SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
244 VERSION_1, 0);
245
246 /* Fill BL3-2 related information if it exists */
Victor Chong043741c2017-09-14 01:22:14 +0900247#ifdef BL32_BASE
Haojian Zhuang934ae712017-05-24 08:47:49 +0800248 bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
249 SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
250 VERSION_1, 0);
251 bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
252 SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
253 VERSION_1, 0);
254#endif
255
256 /* Fill BL3-3 related information */
257 bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
258 SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
259 PARAM_EP, VERSION_1, 0);
260
261 /* BL3-3 expects to receive the primary CPU MPID (through x0) */
262 bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
263
264 bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
265 SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
266 VERSION_1, 0);
267
268 return bl2_to_bl31_params;
269}
270
271struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
272{
Victor Chong2d9a42d2017-08-17 15:21:10 +0900273#if DEBUG
274 bl31_params_mem.bl31_ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL;
275#endif
276
Haojian Zhuang934ae712017-05-24 08:47:49 +0800277 return &bl31_params_mem.bl31_ep_info;
278}
279
280void bl2_plat_set_bl31_ep_info(image_info_t *image,
281 entry_point_info_t *bl31_ep_info)
282{
283 SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
284 bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
285 DISABLE_ALL_EXCEPTIONS);
286}
287
Victor Chongb9a8db22017-05-28 00:14:25 +0900288/*******************************************************************************
289 * Before calling this function BL32 is loaded in memory and its entrypoint
290 * is set by load_image. This is a placeholder for the platform to change
291 * the entrypoint of BL32 and set SPSR and security state.
292 * On Hikey we only set the security state of the entrypoint
293 ******************************************************************************/
294#ifdef BL32_BASE
295void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
296 entry_point_info_t *bl32_ep_info)
297{
298 SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
299 /*
300 * The Secure Payload Dispatcher service is responsible for
301 * setting the SPSR prior to entry into the BL32 image.
302 */
303 bl32_ep_info->spsr = 0;
304}
305
306/*******************************************************************************
307 * Populate the extents of memory available for loading BL32
308 ******************************************************************************/
309void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
310{
311 /*
312 * Populate the extents of memory available for loading BL32.
313 */
314 bl32_meminfo->total_base = BL32_BASE;
315 bl32_meminfo->free_base = BL32_BASE;
316 bl32_meminfo->total_size =
317 (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
318 bl32_meminfo->free_size =
319 (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
320}
321#endif /* BL32_BASE */
322
Haojian Zhuang934ae712017-05-24 08:47:49 +0800323void bl2_plat_set_bl33_ep_info(image_info_t *image,
324 entry_point_info_t *bl33_ep_info)
325{
326 unsigned long el_status;
327 unsigned int mode;
328
329 /* Figure out what mode we enter the non-secure world in */
330 el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
331 el_status &= ID_AA64PFR0_ELX_MASK;
332
333 if (el_status)
334 mode = MODE_EL2;
335 else
336 mode = MODE_EL1;
337
338 /*
339 * TODO: Consider the possibility of specifying the SPSR in
340 * the FIP ToC and allowing the platform to have a say as
341 * well.
342 */
343 bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX,
344 DISABLE_ALL_EXCEPTIONS);
345 SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
346}
347
348void bl2_plat_flush_bl31_params(void)
349{
350 flush_dcache_range((unsigned long)&bl31_params_mem,
351 sizeof(bl2_to_bl31_params_mem_t));
352}
353
354void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
355{
356 bl33_meminfo->total_base = DDR_BASE;
357 bl33_meminfo->total_size = DDR_SIZE;
358 bl33_meminfo->free_base = DDR_BASE;
359 bl33_meminfo->free_size = DDR_SIZE;
360}
Victor Chong2d9a42d2017-08-17 15:21:10 +0900361#endif /* LOAD_IMAGE_V2 */
Haojian Zhuang934ae712017-05-24 08:47:49 +0800362
363static void reset_dwmmc_clk(void)
364{
365 unsigned int data;
366
367 /* disable mmc0 bus clock */
368 mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
369 do {
370 data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
371 } while (data & PERI_CLK0_MMC0);
372 /* enable mmc0 bus clock */
373 mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
374 do {
375 data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
376 } while (!(data & PERI_CLK0_MMC0));
377 /* reset mmc0 clock domain */
378 mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
379
380 /* bypass mmc0 clock phase */
381 data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
382 data |= 3;
383 mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
384
385 /* disable low power */
386 data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
387 data |= 1 << 3;
388 mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
389 do {
390 data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
391 } while (!(data & PERI_RST0_MMC0));
392
393 /* unreset mmc0 clock domain */
394 mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
395 do {
396 data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
397 } while (data & PERI_RST0_MMC0);
398}
399
400static void hikey_boardid_init(void)
401{
402 u_register_t midr;
403
404 midr = read_midr();
405 mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr);
406 INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR,
407 (unsigned int)midr);
408
409 mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0);
410 mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b);
411
412 mmio_write_32(ACPU_ARM64_FLAGA, 0x1234);
413 mmio_write_32(ACPU_ARM64_FLAGB, 0x5678);
414}
415
416static void hikey_sd_init(void)
417{
418 /* switch pinmux to SD */
419 mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0);
420 mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0);
421 mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0);
422 mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0);
423 mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0);
424 mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0);
425
426 mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA);
427 mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA);
428 mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA);
429 mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA);
430 mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA);
431 mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA);
432
433 /* set SD Card detect as nopull */
434 mmio_write_32(IOCG_GPIO8, 0);
435}
436
437static void hikey_jumper_init(void)
438{
439 /* set jumper detect as nopull */
440 mmio_write_32(IOCG_GPIO24, 0);
441 /* set jumper detect as GPIO */
442 mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0);
443}
444
445void bl2_early_platform_setup(meminfo_t *mem_layout)
446{
447 dw_mmc_params_t params;
448
449 /* Initialize the console to provide early debug support */
450 console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
451
452 /* Setup the BL2 memory layout */
453 bl2_tzram_layout = *mem_layout;
454
455 /* Clear SRAM since it'll be used by MCU right now. */
456 memset((void *)SRAM_BASE, 0, SRAM_SIZE);
457
458 sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
459 dsb();
460 hikey_ddr_init();
461
462 hikey_boardid_init();
463 init_acpu_dvfs();
464 hikey_sd_init();
465 hikey_jumper_init();
466
467 reset_dwmmc_clk();
468 memset(&params, 0, sizeof(dw_mmc_params_t));
469 params.reg_base = DWMMC0_BASE;
470 params.desc_base = HIKEY_MMC_DESC_BASE;
471 params.desc_size = 1 << 20;
472 params.clk_rate = 24 * 1000 * 1000;
473 params.bus_width = EMMC_BUS_WIDTH_8;
474 params.flags = EMMC_FLAG_CMD23;
475 dw_mmc_init(&params);
476
477 hikey_io_setup();
478}
479
480void bl2_plat_arch_setup(void)
481{
482 hikey_init_mmu_el1(bl2_tzram_layout.total_base,
483 bl2_tzram_layout.total_size,
484 BL2_RO_BASE,
485 BL2_RO_LIMIT,
486 BL2_COHERENT_RAM_BASE,
487 BL2_COHERENT_RAM_LIMIT);
488}
489
490void bl2_platform_setup(void)
491{
Jerome Forissierc52e55f2015-05-04 09:40:03 +0200492 hikey_security_setup();
Haojian Zhuang934ae712017-05-24 08:47:49 +0800493}