132e9fc1aSHaojian Zhuang /* 232e9fc1aSHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 332e9fc1aSHaojian Zhuang * 432e9fc1aSHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 532e9fc1aSHaojian Zhuang */ 632e9fc1aSHaojian Zhuang 732e9fc1aSHaojian Zhuang #include <arch_helpers.h> 832e9fc1aSHaojian Zhuang #include <assert.h> 932e9fc1aSHaojian Zhuang #include <bl_common.h> 1032e9fc1aSHaojian Zhuang #include <console.h> 1132e9fc1aSHaojian Zhuang #include <debug.h> 122de0c5ccSVictor Chong #include <desc_image_load.h> 1332e9fc1aSHaojian Zhuang #include <dw_mmc.h> 1432e9fc1aSHaojian Zhuang #include <emmc.h> 1532e9fc1aSHaojian Zhuang #include <errno.h> 1632e9fc1aSHaojian Zhuang #include <hi6220.h> 1732e9fc1aSHaojian Zhuang #include <hisi_mcu.h> 1832e9fc1aSHaojian Zhuang #include <hisi_sram_map.h> 1932e9fc1aSHaojian Zhuang #include <mmio.h> 20*b16bb16eSVictor Chong #if LOAD_IMAGE_V2 21*b16bb16eSVictor Chong #ifdef SPD_opteed 22*b16bb16eSVictor Chong #include <optee_utils.h> 23*b16bb16eSVictor Chong #endif 24*b16bb16eSVictor Chong #endif 2532e9fc1aSHaojian Zhuang #include <platform_def.h> 2632e9fc1aSHaojian Zhuang #include <sp804_delay_timer.h> 2732e9fc1aSHaojian Zhuang #include <string.h> 2832e9fc1aSHaojian Zhuang 2932e9fc1aSHaojian Zhuang #include "hikey_def.h" 3032e9fc1aSHaojian Zhuang #include "hikey_private.h" 3132e9fc1aSHaojian Zhuang 3232e9fc1aSHaojian Zhuang /* 3332e9fc1aSHaojian Zhuang * The next 2 constants identify the extents of the code & RO data region. 3432e9fc1aSHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 3532e9fc1aSHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 3632e9fc1aSHaojian Zhuang * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. 3732e9fc1aSHaojian Zhuang */ 3832e9fc1aSHaojian Zhuang #define BL2_RO_BASE (unsigned long)(&__RO_START__) 3932e9fc1aSHaojian Zhuang #define BL2_RO_LIMIT (unsigned long)(&__RO_END__) 4032e9fc1aSHaojian Zhuang 4132e9fc1aSHaojian Zhuang /* 4232e9fc1aSHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 4332e9fc1aSHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 4432e9fc1aSHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 4532e9fc1aSHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 4632e9fc1aSHaojian Zhuang * page-aligned addresses. 4732e9fc1aSHaojian Zhuang */ 4832e9fc1aSHaojian Zhuang #define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 4932e9fc1aSHaojian Zhuang #define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 5032e9fc1aSHaojian Zhuang 5132e9fc1aSHaojian Zhuang static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); 5232e9fc1aSHaojian Zhuang 532de0c5ccSVictor Chong #if !LOAD_IMAGE_V2 542de0c5ccSVictor Chong 552de0c5ccSVictor Chong /******************************************************************************* 562de0c5ccSVictor Chong * This structure represents the superset of information that is passed to 572de0c5ccSVictor Chong * BL31, e.g. while passing control to it from BL2, bl31_params 582de0c5ccSVictor Chong * and other platform specific params 592de0c5ccSVictor Chong ******************************************************************************/ 6032e9fc1aSHaojian Zhuang typedef struct bl2_to_bl31_params_mem { 6132e9fc1aSHaojian Zhuang bl31_params_t bl31_params; 6232e9fc1aSHaojian Zhuang image_info_t bl31_image_info; 6332e9fc1aSHaojian Zhuang image_info_t bl32_image_info; 6432e9fc1aSHaojian Zhuang image_info_t bl33_image_info; 6532e9fc1aSHaojian Zhuang entry_point_info_t bl33_ep_info; 6632e9fc1aSHaojian Zhuang entry_point_info_t bl32_ep_info; 6732e9fc1aSHaojian Zhuang entry_point_info_t bl31_ep_info; 6832e9fc1aSHaojian Zhuang } bl2_to_bl31_params_mem_t; 6932e9fc1aSHaojian Zhuang 7032e9fc1aSHaojian Zhuang static bl2_to_bl31_params_mem_t bl31_params_mem; 7132e9fc1aSHaojian Zhuang 7232e9fc1aSHaojian Zhuang meminfo_t *bl2_plat_sec_mem_layout(void) 7332e9fc1aSHaojian Zhuang { 7432e9fc1aSHaojian Zhuang return &bl2_tzram_layout; 7532e9fc1aSHaojian Zhuang } 7632e9fc1aSHaojian Zhuang 7732e9fc1aSHaojian Zhuang void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo) 7832e9fc1aSHaojian Zhuang { 7932e9fc1aSHaojian Zhuang scp_bl2_meminfo->total_base = SCP_BL2_BASE; 8032e9fc1aSHaojian Zhuang scp_bl2_meminfo->total_size = SCP_BL2_SIZE; 8132e9fc1aSHaojian Zhuang scp_bl2_meminfo->free_base = SCP_BL2_BASE; 8232e9fc1aSHaojian Zhuang scp_bl2_meminfo->free_size = SCP_BL2_SIZE; 8332e9fc1aSHaojian Zhuang } 842de0c5ccSVictor Chong #endif /* LOAD_IMAGE_V2 */ 8532e9fc1aSHaojian Zhuang 862de0c5ccSVictor Chong /******************************************************************************* 872de0c5ccSVictor Chong * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. 882de0c5ccSVictor Chong * Return 0 on success, -1 otherwise. 892de0c5ccSVictor Chong ******************************************************************************/ 902de0c5ccSVictor Chong #if LOAD_IMAGE_V2 912de0c5ccSVictor Chong int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) 922de0c5ccSVictor Chong #else 9332e9fc1aSHaojian Zhuang int bl2_plat_handle_scp_bl2(struct image_info *scp_bl2_image_info) 942de0c5ccSVictor Chong #endif 9532e9fc1aSHaojian Zhuang { 9632e9fc1aSHaojian Zhuang /* Enable MCU SRAM */ 9732e9fc1aSHaojian Zhuang hisi_mcu_enable_sram(); 9832e9fc1aSHaojian Zhuang 9932e9fc1aSHaojian Zhuang /* Load MCU binary into SRAM */ 10032e9fc1aSHaojian Zhuang hisi_mcu_load_image(scp_bl2_image_info->image_base, 10132e9fc1aSHaojian Zhuang scp_bl2_image_info->image_size); 10232e9fc1aSHaojian Zhuang /* Let MCU running */ 10332e9fc1aSHaojian Zhuang hisi_mcu_start_run(); 10432e9fc1aSHaojian Zhuang 10532e9fc1aSHaojian Zhuang INFO("%s: MCU PC is at 0x%x\n", 10632e9fc1aSHaojian Zhuang __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2)); 10732e9fc1aSHaojian Zhuang INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n", 10832e9fc1aSHaojian Zhuang __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4)); 10932e9fc1aSHaojian Zhuang return 0; 11032e9fc1aSHaojian Zhuang } 11132e9fc1aSHaojian Zhuang 1122de0c5ccSVictor Chong /******************************************************************************* 1132de0c5ccSVictor Chong * Gets SPSR for BL32 entry 1142de0c5ccSVictor Chong ******************************************************************************/ 1152de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl32_entry(void) 1162de0c5ccSVictor Chong { 1172de0c5ccSVictor Chong /* 1182de0c5ccSVictor Chong * The Secure Payload Dispatcher service is responsible for 1192de0c5ccSVictor Chong * setting the SPSR prior to entry into the BL3-2 image. 1202de0c5ccSVictor Chong */ 1212de0c5ccSVictor Chong return 0; 1222de0c5ccSVictor Chong } 1232de0c5ccSVictor Chong 1242de0c5ccSVictor Chong /******************************************************************************* 1252de0c5ccSVictor Chong * Gets SPSR for BL33 entry 1262de0c5ccSVictor Chong ******************************************************************************/ 1272de0c5ccSVictor Chong #ifndef AARCH32 1282de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl33_entry(void) 1292de0c5ccSVictor Chong { 1302de0c5ccSVictor Chong unsigned int mode; 1312de0c5ccSVictor Chong uint32_t spsr; 1322de0c5ccSVictor Chong 1332de0c5ccSVictor Chong /* Figure out what mode we enter the non-secure world in */ 1342de0c5ccSVictor Chong mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1; 1352de0c5ccSVictor Chong 1362de0c5ccSVictor Chong /* 1372de0c5ccSVictor Chong * TODO: Consider the possibility of specifying the SPSR in 1382de0c5ccSVictor Chong * the FIP ToC and allowing the platform to have a say as 1392de0c5ccSVictor Chong * well. 1402de0c5ccSVictor Chong */ 1412de0c5ccSVictor Chong spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 1422de0c5ccSVictor Chong return spsr; 1432de0c5ccSVictor Chong } 1442de0c5ccSVictor Chong #else 1452de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl33_entry(void) 1462de0c5ccSVictor Chong { 1472de0c5ccSVictor Chong unsigned int hyp_status, mode, spsr; 1482de0c5ccSVictor Chong 1492de0c5ccSVictor Chong hyp_status = GET_VIRT_EXT(read_id_pfr1()); 1502de0c5ccSVictor Chong 1512de0c5ccSVictor Chong mode = (hyp_status) ? MODE32_hyp : MODE32_svc; 1522de0c5ccSVictor Chong 1532de0c5ccSVictor Chong /* 1542de0c5ccSVictor Chong * TODO: Consider the possibility of specifying the SPSR in 1552de0c5ccSVictor Chong * the FIP ToC and allowing the platform to have a say as 1562de0c5ccSVictor Chong * well. 1572de0c5ccSVictor Chong */ 1582de0c5ccSVictor Chong spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, 1592de0c5ccSVictor Chong SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); 1602de0c5ccSVictor Chong return spsr; 1612de0c5ccSVictor Chong } 1622de0c5ccSVictor Chong #endif /* AARCH32 */ 1632de0c5ccSVictor Chong 1642de0c5ccSVictor Chong #if LOAD_IMAGE_V2 1652de0c5ccSVictor Chong int hikey_bl2_handle_post_image_load(unsigned int image_id) 1662de0c5ccSVictor Chong { 1672de0c5ccSVictor Chong int err = 0; 1682de0c5ccSVictor Chong bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); 169*b16bb16eSVictor Chong #ifdef SPD_opteed 170*b16bb16eSVictor Chong bl_mem_params_node_t *pager_mem_params = NULL; 171*b16bb16eSVictor Chong bl_mem_params_node_t *paged_mem_params = NULL; 172*b16bb16eSVictor Chong #endif 1732de0c5ccSVictor Chong assert(bl_mem_params); 1742de0c5ccSVictor Chong 1752de0c5ccSVictor Chong switch (image_id) { 1762de0c5ccSVictor Chong #ifdef AARCH64 1772de0c5ccSVictor Chong case BL32_IMAGE_ID: 178*b16bb16eSVictor Chong #ifdef SPD_opteed 179*b16bb16eSVictor Chong pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); 180*b16bb16eSVictor Chong assert(pager_mem_params); 181*b16bb16eSVictor Chong 182*b16bb16eSVictor Chong paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); 183*b16bb16eSVictor Chong assert(paged_mem_params); 184*b16bb16eSVictor Chong 185*b16bb16eSVictor Chong err = parse_optee_header(&bl_mem_params->ep_info, 186*b16bb16eSVictor Chong &pager_mem_params->image_info, 187*b16bb16eSVictor Chong &paged_mem_params->image_info); 188*b16bb16eSVictor Chong if (err != 0) { 189*b16bb16eSVictor Chong WARN("OPTEE header parse error.\n"); 190*b16bb16eSVictor Chong } 191*b16bb16eSVictor Chong #endif 1922de0c5ccSVictor Chong bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry(); 1932de0c5ccSVictor Chong break; 1942de0c5ccSVictor Chong #endif 1952de0c5ccSVictor Chong 1962de0c5ccSVictor Chong case BL33_IMAGE_ID: 1972de0c5ccSVictor Chong /* BL33 expects to receive the primary CPU MPID (through r0) */ 1982de0c5ccSVictor Chong bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); 1992de0c5ccSVictor Chong bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry(); 2002de0c5ccSVictor Chong break; 2012de0c5ccSVictor Chong 2022de0c5ccSVictor Chong #ifdef SCP_BL2_BASE 2032de0c5ccSVictor Chong case SCP_BL2_IMAGE_ID: 2042de0c5ccSVictor Chong /* The subsequent handling of SCP_BL2 is platform specific */ 2052de0c5ccSVictor Chong err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info); 2062de0c5ccSVictor Chong if (err) { 2072de0c5ccSVictor Chong WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); 2082de0c5ccSVictor Chong } 2092de0c5ccSVictor Chong break; 2102de0c5ccSVictor Chong #endif 2112de0c5ccSVictor Chong } 2122de0c5ccSVictor Chong 2132de0c5ccSVictor Chong return err; 2142de0c5ccSVictor Chong } 2152de0c5ccSVictor Chong 2162de0c5ccSVictor Chong /******************************************************************************* 2172de0c5ccSVictor Chong * This function can be used by the platforms to update/use image 2182de0c5ccSVictor Chong * information for given `image_id`. 2192de0c5ccSVictor Chong ******************************************************************************/ 2202de0c5ccSVictor Chong int bl2_plat_handle_post_image_load(unsigned int image_id) 2212de0c5ccSVictor Chong { 2222de0c5ccSVictor Chong return hikey_bl2_handle_post_image_load(image_id); 2232de0c5ccSVictor Chong } 2242de0c5ccSVictor Chong 2252de0c5ccSVictor Chong #else /* LOAD_IMAGE_V2 */ 2262de0c5ccSVictor Chong 22732e9fc1aSHaojian Zhuang bl31_params_t *bl2_plat_get_bl31_params(void) 22832e9fc1aSHaojian Zhuang { 22932e9fc1aSHaojian Zhuang bl31_params_t *bl2_to_bl31_params = NULL; 23032e9fc1aSHaojian Zhuang 23132e9fc1aSHaojian Zhuang /* 23232e9fc1aSHaojian Zhuang * Initialise the memory for all the arguments that needs to 23332e9fc1aSHaojian Zhuang * be passed to BL3-1 23432e9fc1aSHaojian Zhuang */ 23532e9fc1aSHaojian Zhuang memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); 23632e9fc1aSHaojian Zhuang 23732e9fc1aSHaojian Zhuang /* Assign memory for TF related information */ 23832e9fc1aSHaojian Zhuang bl2_to_bl31_params = &bl31_params_mem.bl31_params; 23932e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); 24032e9fc1aSHaojian Zhuang 24132e9fc1aSHaojian Zhuang /* Fill BL3-1 related information */ 24232e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; 24332e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, 24432e9fc1aSHaojian Zhuang VERSION_1, 0); 24532e9fc1aSHaojian Zhuang 24632e9fc1aSHaojian Zhuang /* Fill BL3-2 related information if it exists */ 24732e9fc1aSHaojian Zhuang #if BL32_BASE 24832e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; 24932e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, 25032e9fc1aSHaojian Zhuang VERSION_1, 0); 25132e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; 25232e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, 25332e9fc1aSHaojian Zhuang VERSION_1, 0); 25432e9fc1aSHaojian Zhuang #endif 25532e9fc1aSHaojian Zhuang 25632e9fc1aSHaojian Zhuang /* Fill BL3-3 related information */ 25732e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; 25832e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, 25932e9fc1aSHaojian Zhuang PARAM_EP, VERSION_1, 0); 26032e9fc1aSHaojian Zhuang 26132e9fc1aSHaojian Zhuang /* BL3-3 expects to receive the primary CPU MPID (through x0) */ 26232e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); 26332e9fc1aSHaojian Zhuang 26432e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; 26532e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, 26632e9fc1aSHaojian Zhuang VERSION_1, 0); 26732e9fc1aSHaojian Zhuang 26832e9fc1aSHaojian Zhuang return bl2_to_bl31_params; 26932e9fc1aSHaojian Zhuang } 27032e9fc1aSHaojian Zhuang 27132e9fc1aSHaojian Zhuang struct entry_point_info *bl2_plat_get_bl31_ep_info(void) 27232e9fc1aSHaojian Zhuang { 2732de0c5ccSVictor Chong #if DEBUG 2742de0c5ccSVictor Chong bl31_params_mem.bl31_ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL; 2752de0c5ccSVictor Chong #endif 2762de0c5ccSVictor Chong 27732e9fc1aSHaojian Zhuang return &bl31_params_mem.bl31_ep_info; 27832e9fc1aSHaojian Zhuang } 27932e9fc1aSHaojian Zhuang 28032e9fc1aSHaojian Zhuang void bl2_plat_set_bl31_ep_info(image_info_t *image, 28132e9fc1aSHaojian Zhuang entry_point_info_t *bl31_ep_info) 28232e9fc1aSHaojian Zhuang { 28332e9fc1aSHaojian Zhuang SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); 28432e9fc1aSHaojian Zhuang bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, 28532e9fc1aSHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 28632e9fc1aSHaojian Zhuang } 28732e9fc1aSHaojian Zhuang 2883b6e88a2SVictor Chong /******************************************************************************* 2893b6e88a2SVictor Chong * Before calling this function BL32 is loaded in memory and its entrypoint 2903b6e88a2SVictor Chong * is set by load_image. This is a placeholder for the platform to change 2913b6e88a2SVictor Chong * the entrypoint of BL32 and set SPSR and security state. 2923b6e88a2SVictor Chong * On Hikey we only set the security state of the entrypoint 2933b6e88a2SVictor Chong ******************************************************************************/ 2943b6e88a2SVictor Chong #ifdef BL32_BASE 2953b6e88a2SVictor Chong void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, 2963b6e88a2SVictor Chong entry_point_info_t *bl32_ep_info) 2973b6e88a2SVictor Chong { 2983b6e88a2SVictor Chong SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); 2993b6e88a2SVictor Chong /* 3003b6e88a2SVictor Chong * The Secure Payload Dispatcher service is responsible for 3013b6e88a2SVictor Chong * setting the SPSR prior to entry into the BL32 image. 3023b6e88a2SVictor Chong */ 3033b6e88a2SVictor Chong bl32_ep_info->spsr = 0; 3043b6e88a2SVictor Chong } 3053b6e88a2SVictor Chong 3063b6e88a2SVictor Chong /******************************************************************************* 3073b6e88a2SVictor Chong * Populate the extents of memory available for loading BL32 3083b6e88a2SVictor Chong ******************************************************************************/ 3093b6e88a2SVictor Chong void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) 3103b6e88a2SVictor Chong { 3113b6e88a2SVictor Chong /* 3123b6e88a2SVictor Chong * Populate the extents of memory available for loading BL32. 3133b6e88a2SVictor Chong */ 3143b6e88a2SVictor Chong bl32_meminfo->total_base = BL32_BASE; 3153b6e88a2SVictor Chong bl32_meminfo->free_base = BL32_BASE; 3163b6e88a2SVictor Chong bl32_meminfo->total_size = 3173b6e88a2SVictor Chong (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; 3183b6e88a2SVictor Chong bl32_meminfo->free_size = 3193b6e88a2SVictor Chong (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; 3203b6e88a2SVictor Chong } 3213b6e88a2SVictor Chong #endif /* BL32_BASE */ 3223b6e88a2SVictor Chong 32332e9fc1aSHaojian Zhuang void bl2_plat_set_bl33_ep_info(image_info_t *image, 32432e9fc1aSHaojian Zhuang entry_point_info_t *bl33_ep_info) 32532e9fc1aSHaojian Zhuang { 32632e9fc1aSHaojian Zhuang unsigned long el_status; 32732e9fc1aSHaojian Zhuang unsigned int mode; 32832e9fc1aSHaojian Zhuang 32932e9fc1aSHaojian Zhuang /* Figure out what mode we enter the non-secure world in */ 33032e9fc1aSHaojian Zhuang el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; 33132e9fc1aSHaojian Zhuang el_status &= ID_AA64PFR0_ELX_MASK; 33232e9fc1aSHaojian Zhuang 33332e9fc1aSHaojian Zhuang if (el_status) 33432e9fc1aSHaojian Zhuang mode = MODE_EL2; 33532e9fc1aSHaojian Zhuang else 33632e9fc1aSHaojian Zhuang mode = MODE_EL1; 33732e9fc1aSHaojian Zhuang 33832e9fc1aSHaojian Zhuang /* 33932e9fc1aSHaojian Zhuang * TODO: Consider the possibility of specifying the SPSR in 34032e9fc1aSHaojian Zhuang * the FIP ToC and allowing the platform to have a say as 34132e9fc1aSHaojian Zhuang * well. 34232e9fc1aSHaojian Zhuang */ 34332e9fc1aSHaojian Zhuang bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX, 34432e9fc1aSHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 34532e9fc1aSHaojian Zhuang SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); 34632e9fc1aSHaojian Zhuang } 34732e9fc1aSHaojian Zhuang 34832e9fc1aSHaojian Zhuang void bl2_plat_flush_bl31_params(void) 34932e9fc1aSHaojian Zhuang { 35032e9fc1aSHaojian Zhuang flush_dcache_range((unsigned long)&bl31_params_mem, 35132e9fc1aSHaojian Zhuang sizeof(bl2_to_bl31_params_mem_t)); 35232e9fc1aSHaojian Zhuang } 35332e9fc1aSHaojian Zhuang 35432e9fc1aSHaojian Zhuang void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) 35532e9fc1aSHaojian Zhuang { 35632e9fc1aSHaojian Zhuang bl33_meminfo->total_base = DDR_BASE; 35732e9fc1aSHaojian Zhuang bl33_meminfo->total_size = DDR_SIZE; 35832e9fc1aSHaojian Zhuang bl33_meminfo->free_base = DDR_BASE; 35932e9fc1aSHaojian Zhuang bl33_meminfo->free_size = DDR_SIZE; 36032e9fc1aSHaojian Zhuang } 3612de0c5ccSVictor Chong #endif /* LOAD_IMAGE_V2 */ 36232e9fc1aSHaojian Zhuang 36332e9fc1aSHaojian Zhuang static void reset_dwmmc_clk(void) 36432e9fc1aSHaojian Zhuang { 36532e9fc1aSHaojian Zhuang unsigned int data; 36632e9fc1aSHaojian Zhuang 36732e9fc1aSHaojian Zhuang /* disable mmc0 bus clock */ 36832e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); 36932e9fc1aSHaojian Zhuang do { 37032e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 37132e9fc1aSHaojian Zhuang } while (data & PERI_CLK0_MMC0); 37232e9fc1aSHaojian Zhuang /* enable mmc0 bus clock */ 37332e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); 37432e9fc1aSHaojian Zhuang do { 37532e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 37632e9fc1aSHaojian Zhuang } while (!(data & PERI_CLK0_MMC0)); 37732e9fc1aSHaojian Zhuang /* reset mmc0 clock domain */ 37832e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); 37932e9fc1aSHaojian Zhuang 38032e9fc1aSHaojian Zhuang /* bypass mmc0 clock phase */ 38132e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL2); 38232e9fc1aSHaojian Zhuang data |= 3; 38332e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL2, data); 38432e9fc1aSHaojian Zhuang 38532e9fc1aSHaojian Zhuang /* disable low power */ 38632e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL13); 38732e9fc1aSHaojian Zhuang data |= 1 << 3; 38832e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL13, data); 38932e9fc1aSHaojian Zhuang do { 39032e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 39132e9fc1aSHaojian Zhuang } while (!(data & PERI_RST0_MMC0)); 39232e9fc1aSHaojian Zhuang 39332e9fc1aSHaojian Zhuang /* unreset mmc0 clock domain */ 39432e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); 39532e9fc1aSHaojian Zhuang do { 39632e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 39732e9fc1aSHaojian Zhuang } while (data & PERI_RST0_MMC0); 39832e9fc1aSHaojian Zhuang } 39932e9fc1aSHaojian Zhuang 40032e9fc1aSHaojian Zhuang static void hikey_boardid_init(void) 40132e9fc1aSHaojian Zhuang { 40232e9fc1aSHaojian Zhuang u_register_t midr; 40332e9fc1aSHaojian Zhuang 40432e9fc1aSHaojian Zhuang midr = read_midr(); 40532e9fc1aSHaojian Zhuang mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr); 40632e9fc1aSHaojian Zhuang INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, 40732e9fc1aSHaojian Zhuang (unsigned int)midr); 40832e9fc1aSHaojian Zhuang 40932e9fc1aSHaojian Zhuang mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0); 41032e9fc1aSHaojian Zhuang mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b); 41132e9fc1aSHaojian Zhuang 41232e9fc1aSHaojian Zhuang mmio_write_32(ACPU_ARM64_FLAGA, 0x1234); 41332e9fc1aSHaojian Zhuang mmio_write_32(ACPU_ARM64_FLAGB, 0x5678); 41432e9fc1aSHaojian Zhuang } 41532e9fc1aSHaojian Zhuang 41632e9fc1aSHaojian Zhuang static void hikey_sd_init(void) 41732e9fc1aSHaojian Zhuang { 41832e9fc1aSHaojian Zhuang /* switch pinmux to SD */ 41932e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0); 42032e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0); 42132e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0); 42232e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0); 42332e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0); 42432e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0); 42532e9fc1aSHaojian Zhuang 42632e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA); 42732e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA); 42832e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA); 42932e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA); 43032e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA); 43132e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA); 43232e9fc1aSHaojian Zhuang 43332e9fc1aSHaojian Zhuang /* set SD Card detect as nopull */ 43432e9fc1aSHaojian Zhuang mmio_write_32(IOCG_GPIO8, 0); 43532e9fc1aSHaojian Zhuang } 43632e9fc1aSHaojian Zhuang 43732e9fc1aSHaojian Zhuang static void hikey_jumper_init(void) 43832e9fc1aSHaojian Zhuang { 43932e9fc1aSHaojian Zhuang /* set jumper detect as nopull */ 44032e9fc1aSHaojian Zhuang mmio_write_32(IOCG_GPIO24, 0); 44132e9fc1aSHaojian Zhuang /* set jumper detect as GPIO */ 44232e9fc1aSHaojian Zhuang mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0); 44332e9fc1aSHaojian Zhuang } 44432e9fc1aSHaojian Zhuang 44532e9fc1aSHaojian Zhuang void bl2_early_platform_setup(meminfo_t *mem_layout) 44632e9fc1aSHaojian Zhuang { 44732e9fc1aSHaojian Zhuang dw_mmc_params_t params; 44832e9fc1aSHaojian Zhuang 44932e9fc1aSHaojian Zhuang /* Initialize the console to provide early debug support */ 45032e9fc1aSHaojian Zhuang console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 45132e9fc1aSHaojian Zhuang 45232e9fc1aSHaojian Zhuang /* Setup the BL2 memory layout */ 45332e9fc1aSHaojian Zhuang bl2_tzram_layout = *mem_layout; 45432e9fc1aSHaojian Zhuang 45532e9fc1aSHaojian Zhuang /* Clear SRAM since it'll be used by MCU right now. */ 45632e9fc1aSHaojian Zhuang memset((void *)SRAM_BASE, 0, SRAM_SIZE); 45732e9fc1aSHaojian Zhuang 45832e9fc1aSHaojian Zhuang sp804_timer_init(SP804_TIMER0_BASE, 10, 192); 45932e9fc1aSHaojian Zhuang dsb(); 46032e9fc1aSHaojian Zhuang hikey_ddr_init(); 46132e9fc1aSHaojian Zhuang 46232e9fc1aSHaojian Zhuang hikey_boardid_init(); 46332e9fc1aSHaojian Zhuang init_acpu_dvfs(); 46432e9fc1aSHaojian Zhuang hikey_sd_init(); 46532e9fc1aSHaojian Zhuang hikey_jumper_init(); 46632e9fc1aSHaojian Zhuang 46732e9fc1aSHaojian Zhuang reset_dwmmc_clk(); 46832e9fc1aSHaojian Zhuang memset(¶ms, 0, sizeof(dw_mmc_params_t)); 46932e9fc1aSHaojian Zhuang params.reg_base = DWMMC0_BASE; 47032e9fc1aSHaojian Zhuang params.desc_base = HIKEY_MMC_DESC_BASE; 47132e9fc1aSHaojian Zhuang params.desc_size = 1 << 20; 47232e9fc1aSHaojian Zhuang params.clk_rate = 24 * 1000 * 1000; 47332e9fc1aSHaojian Zhuang params.bus_width = EMMC_BUS_WIDTH_8; 47432e9fc1aSHaojian Zhuang params.flags = EMMC_FLAG_CMD23; 47532e9fc1aSHaojian Zhuang dw_mmc_init(¶ms); 47632e9fc1aSHaojian Zhuang 47732e9fc1aSHaojian Zhuang hikey_io_setup(); 47832e9fc1aSHaojian Zhuang } 47932e9fc1aSHaojian Zhuang 48032e9fc1aSHaojian Zhuang void bl2_plat_arch_setup(void) 48132e9fc1aSHaojian Zhuang { 48232e9fc1aSHaojian Zhuang hikey_init_mmu_el1(bl2_tzram_layout.total_base, 48332e9fc1aSHaojian Zhuang bl2_tzram_layout.total_size, 48432e9fc1aSHaojian Zhuang BL2_RO_BASE, 48532e9fc1aSHaojian Zhuang BL2_RO_LIMIT, 48632e9fc1aSHaojian Zhuang BL2_COHERENT_RAM_BASE, 48732e9fc1aSHaojian Zhuang BL2_COHERENT_RAM_LIMIT); 48832e9fc1aSHaojian Zhuang } 48932e9fc1aSHaojian Zhuang 49032e9fc1aSHaojian Zhuang void bl2_platform_setup(void) 49132e9fc1aSHaojian Zhuang { 49232e9fc1aSHaojian Zhuang } 493