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> 12*2de0c5ccSVictor 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> 2032e9fc1aSHaojian Zhuang #include <platform_def.h> 2132e9fc1aSHaojian Zhuang #include <sp804_delay_timer.h> 2232e9fc1aSHaojian Zhuang #include <string.h> 2332e9fc1aSHaojian Zhuang 2432e9fc1aSHaojian Zhuang #include "hikey_def.h" 2532e9fc1aSHaojian Zhuang #include "hikey_private.h" 2632e9fc1aSHaojian Zhuang 2732e9fc1aSHaojian Zhuang /* 2832e9fc1aSHaojian Zhuang * The next 2 constants identify the extents of the code & RO data region. 2932e9fc1aSHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 3032e9fc1aSHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 3132e9fc1aSHaojian Zhuang * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. 3232e9fc1aSHaojian Zhuang */ 3332e9fc1aSHaojian Zhuang #define BL2_RO_BASE (unsigned long)(&__RO_START__) 3432e9fc1aSHaojian Zhuang #define BL2_RO_LIMIT (unsigned long)(&__RO_END__) 3532e9fc1aSHaojian Zhuang 3632e9fc1aSHaojian Zhuang /* 3732e9fc1aSHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 3832e9fc1aSHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 3932e9fc1aSHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 4032e9fc1aSHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 4132e9fc1aSHaojian Zhuang * page-aligned addresses. 4232e9fc1aSHaojian Zhuang */ 4332e9fc1aSHaojian Zhuang #define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 4432e9fc1aSHaojian Zhuang #define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 4532e9fc1aSHaojian Zhuang 4632e9fc1aSHaojian Zhuang static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); 4732e9fc1aSHaojian Zhuang 48*2de0c5ccSVictor Chong #if !LOAD_IMAGE_V2 49*2de0c5ccSVictor Chong 50*2de0c5ccSVictor Chong /******************************************************************************* 51*2de0c5ccSVictor Chong * This structure represents the superset of information that is passed to 52*2de0c5ccSVictor Chong * BL31, e.g. while passing control to it from BL2, bl31_params 53*2de0c5ccSVictor Chong * and other platform specific params 54*2de0c5ccSVictor Chong ******************************************************************************/ 5532e9fc1aSHaojian Zhuang typedef struct bl2_to_bl31_params_mem { 5632e9fc1aSHaojian Zhuang bl31_params_t bl31_params; 5732e9fc1aSHaojian Zhuang image_info_t bl31_image_info; 5832e9fc1aSHaojian Zhuang image_info_t bl32_image_info; 5932e9fc1aSHaojian Zhuang image_info_t bl33_image_info; 6032e9fc1aSHaojian Zhuang entry_point_info_t bl33_ep_info; 6132e9fc1aSHaojian Zhuang entry_point_info_t bl32_ep_info; 6232e9fc1aSHaojian Zhuang entry_point_info_t bl31_ep_info; 6332e9fc1aSHaojian Zhuang } bl2_to_bl31_params_mem_t; 6432e9fc1aSHaojian Zhuang 6532e9fc1aSHaojian Zhuang static bl2_to_bl31_params_mem_t bl31_params_mem; 6632e9fc1aSHaojian Zhuang 6732e9fc1aSHaojian Zhuang meminfo_t *bl2_plat_sec_mem_layout(void) 6832e9fc1aSHaojian Zhuang { 6932e9fc1aSHaojian Zhuang return &bl2_tzram_layout; 7032e9fc1aSHaojian Zhuang } 7132e9fc1aSHaojian Zhuang 7232e9fc1aSHaojian Zhuang void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo) 7332e9fc1aSHaojian Zhuang { 7432e9fc1aSHaojian Zhuang scp_bl2_meminfo->total_base = SCP_BL2_BASE; 7532e9fc1aSHaojian Zhuang scp_bl2_meminfo->total_size = SCP_BL2_SIZE; 7632e9fc1aSHaojian Zhuang scp_bl2_meminfo->free_base = SCP_BL2_BASE; 7732e9fc1aSHaojian Zhuang scp_bl2_meminfo->free_size = SCP_BL2_SIZE; 7832e9fc1aSHaojian Zhuang } 79*2de0c5ccSVictor Chong #endif /* LOAD_IMAGE_V2 */ 8032e9fc1aSHaojian Zhuang 81*2de0c5ccSVictor Chong /******************************************************************************* 82*2de0c5ccSVictor Chong * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. 83*2de0c5ccSVictor Chong * Return 0 on success, -1 otherwise. 84*2de0c5ccSVictor Chong ******************************************************************************/ 85*2de0c5ccSVictor Chong #if LOAD_IMAGE_V2 86*2de0c5ccSVictor Chong int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) 87*2de0c5ccSVictor Chong #else 8832e9fc1aSHaojian Zhuang int bl2_plat_handle_scp_bl2(struct image_info *scp_bl2_image_info) 89*2de0c5ccSVictor Chong #endif 9032e9fc1aSHaojian Zhuang { 9132e9fc1aSHaojian Zhuang /* Enable MCU SRAM */ 9232e9fc1aSHaojian Zhuang hisi_mcu_enable_sram(); 9332e9fc1aSHaojian Zhuang 9432e9fc1aSHaojian Zhuang /* Load MCU binary into SRAM */ 9532e9fc1aSHaojian Zhuang hisi_mcu_load_image(scp_bl2_image_info->image_base, 9632e9fc1aSHaojian Zhuang scp_bl2_image_info->image_size); 9732e9fc1aSHaojian Zhuang /* Let MCU running */ 9832e9fc1aSHaojian Zhuang hisi_mcu_start_run(); 9932e9fc1aSHaojian Zhuang 10032e9fc1aSHaojian Zhuang INFO("%s: MCU PC is at 0x%x\n", 10132e9fc1aSHaojian Zhuang __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2)); 10232e9fc1aSHaojian Zhuang INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n", 10332e9fc1aSHaojian Zhuang __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4)); 10432e9fc1aSHaojian Zhuang return 0; 10532e9fc1aSHaojian Zhuang } 10632e9fc1aSHaojian Zhuang 107*2de0c5ccSVictor Chong /******************************************************************************* 108*2de0c5ccSVictor Chong * Gets SPSR for BL32 entry 109*2de0c5ccSVictor Chong ******************************************************************************/ 110*2de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl32_entry(void) 111*2de0c5ccSVictor Chong { 112*2de0c5ccSVictor Chong /* 113*2de0c5ccSVictor Chong * The Secure Payload Dispatcher service is responsible for 114*2de0c5ccSVictor Chong * setting the SPSR prior to entry into the BL3-2 image. 115*2de0c5ccSVictor Chong */ 116*2de0c5ccSVictor Chong return 0; 117*2de0c5ccSVictor Chong } 118*2de0c5ccSVictor Chong 119*2de0c5ccSVictor Chong /******************************************************************************* 120*2de0c5ccSVictor Chong * Gets SPSR for BL33 entry 121*2de0c5ccSVictor Chong ******************************************************************************/ 122*2de0c5ccSVictor Chong #ifndef AARCH32 123*2de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl33_entry(void) 124*2de0c5ccSVictor Chong { 125*2de0c5ccSVictor Chong unsigned int mode; 126*2de0c5ccSVictor Chong uint32_t spsr; 127*2de0c5ccSVictor Chong 128*2de0c5ccSVictor Chong /* Figure out what mode we enter the non-secure world in */ 129*2de0c5ccSVictor Chong mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1; 130*2de0c5ccSVictor Chong 131*2de0c5ccSVictor Chong /* 132*2de0c5ccSVictor Chong * TODO: Consider the possibility of specifying the SPSR in 133*2de0c5ccSVictor Chong * the FIP ToC and allowing the platform to have a say as 134*2de0c5ccSVictor Chong * well. 135*2de0c5ccSVictor Chong */ 136*2de0c5ccSVictor Chong spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 137*2de0c5ccSVictor Chong return spsr; 138*2de0c5ccSVictor Chong } 139*2de0c5ccSVictor Chong #else 140*2de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl33_entry(void) 141*2de0c5ccSVictor Chong { 142*2de0c5ccSVictor Chong unsigned int hyp_status, mode, spsr; 143*2de0c5ccSVictor Chong 144*2de0c5ccSVictor Chong hyp_status = GET_VIRT_EXT(read_id_pfr1()); 145*2de0c5ccSVictor Chong 146*2de0c5ccSVictor Chong mode = (hyp_status) ? MODE32_hyp : MODE32_svc; 147*2de0c5ccSVictor Chong 148*2de0c5ccSVictor Chong /* 149*2de0c5ccSVictor Chong * TODO: Consider the possibility of specifying the SPSR in 150*2de0c5ccSVictor Chong * the FIP ToC and allowing the platform to have a say as 151*2de0c5ccSVictor Chong * well. 152*2de0c5ccSVictor Chong */ 153*2de0c5ccSVictor Chong spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, 154*2de0c5ccSVictor Chong SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); 155*2de0c5ccSVictor Chong return spsr; 156*2de0c5ccSVictor Chong } 157*2de0c5ccSVictor Chong #endif /* AARCH32 */ 158*2de0c5ccSVictor Chong 159*2de0c5ccSVictor Chong #if LOAD_IMAGE_V2 160*2de0c5ccSVictor Chong int hikey_bl2_handle_post_image_load(unsigned int image_id) 161*2de0c5ccSVictor Chong { 162*2de0c5ccSVictor Chong int err = 0; 163*2de0c5ccSVictor Chong bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); 164*2de0c5ccSVictor Chong assert(bl_mem_params); 165*2de0c5ccSVictor Chong 166*2de0c5ccSVictor Chong switch (image_id) { 167*2de0c5ccSVictor Chong #ifdef AARCH64 168*2de0c5ccSVictor Chong case BL32_IMAGE_ID: 169*2de0c5ccSVictor Chong bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry(); 170*2de0c5ccSVictor Chong break; 171*2de0c5ccSVictor Chong #endif 172*2de0c5ccSVictor Chong 173*2de0c5ccSVictor Chong case BL33_IMAGE_ID: 174*2de0c5ccSVictor Chong /* BL33 expects to receive the primary CPU MPID (through r0) */ 175*2de0c5ccSVictor Chong bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); 176*2de0c5ccSVictor Chong bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry(); 177*2de0c5ccSVictor Chong break; 178*2de0c5ccSVictor Chong 179*2de0c5ccSVictor Chong #ifdef SCP_BL2_BASE 180*2de0c5ccSVictor Chong case SCP_BL2_IMAGE_ID: 181*2de0c5ccSVictor Chong /* The subsequent handling of SCP_BL2 is platform specific */ 182*2de0c5ccSVictor Chong err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info); 183*2de0c5ccSVictor Chong if (err) { 184*2de0c5ccSVictor Chong WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); 185*2de0c5ccSVictor Chong } 186*2de0c5ccSVictor Chong break; 187*2de0c5ccSVictor Chong #endif 188*2de0c5ccSVictor Chong } 189*2de0c5ccSVictor Chong 190*2de0c5ccSVictor Chong return err; 191*2de0c5ccSVictor Chong } 192*2de0c5ccSVictor Chong 193*2de0c5ccSVictor Chong /******************************************************************************* 194*2de0c5ccSVictor Chong * This function can be used by the platforms to update/use image 195*2de0c5ccSVictor Chong * information for given `image_id`. 196*2de0c5ccSVictor Chong ******************************************************************************/ 197*2de0c5ccSVictor Chong int bl2_plat_handle_post_image_load(unsigned int image_id) 198*2de0c5ccSVictor Chong { 199*2de0c5ccSVictor Chong return hikey_bl2_handle_post_image_load(image_id); 200*2de0c5ccSVictor Chong } 201*2de0c5ccSVictor Chong 202*2de0c5ccSVictor Chong #else /* LOAD_IMAGE_V2 */ 203*2de0c5ccSVictor Chong 20432e9fc1aSHaojian Zhuang bl31_params_t *bl2_plat_get_bl31_params(void) 20532e9fc1aSHaojian Zhuang { 20632e9fc1aSHaojian Zhuang bl31_params_t *bl2_to_bl31_params = NULL; 20732e9fc1aSHaojian Zhuang 20832e9fc1aSHaojian Zhuang /* 20932e9fc1aSHaojian Zhuang * Initialise the memory for all the arguments that needs to 21032e9fc1aSHaojian Zhuang * be passed to BL3-1 21132e9fc1aSHaojian Zhuang */ 21232e9fc1aSHaojian Zhuang memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); 21332e9fc1aSHaojian Zhuang 21432e9fc1aSHaojian Zhuang /* Assign memory for TF related information */ 21532e9fc1aSHaojian Zhuang bl2_to_bl31_params = &bl31_params_mem.bl31_params; 21632e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); 21732e9fc1aSHaojian Zhuang 21832e9fc1aSHaojian Zhuang /* Fill BL3-1 related information */ 21932e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; 22032e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, 22132e9fc1aSHaojian Zhuang VERSION_1, 0); 22232e9fc1aSHaojian Zhuang 22332e9fc1aSHaojian Zhuang /* Fill BL3-2 related information if it exists */ 22432e9fc1aSHaojian Zhuang #if BL32_BASE 22532e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; 22632e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, 22732e9fc1aSHaojian Zhuang VERSION_1, 0); 22832e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; 22932e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, 23032e9fc1aSHaojian Zhuang VERSION_1, 0); 23132e9fc1aSHaojian Zhuang #endif 23232e9fc1aSHaojian Zhuang 23332e9fc1aSHaojian Zhuang /* Fill BL3-3 related information */ 23432e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; 23532e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, 23632e9fc1aSHaojian Zhuang PARAM_EP, VERSION_1, 0); 23732e9fc1aSHaojian Zhuang 23832e9fc1aSHaojian Zhuang /* BL3-3 expects to receive the primary CPU MPID (through x0) */ 23932e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); 24032e9fc1aSHaojian Zhuang 24132e9fc1aSHaojian Zhuang bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; 24232e9fc1aSHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, 24332e9fc1aSHaojian Zhuang VERSION_1, 0); 24432e9fc1aSHaojian Zhuang 24532e9fc1aSHaojian Zhuang return bl2_to_bl31_params; 24632e9fc1aSHaojian Zhuang } 24732e9fc1aSHaojian Zhuang 24832e9fc1aSHaojian Zhuang struct entry_point_info *bl2_plat_get_bl31_ep_info(void) 24932e9fc1aSHaojian Zhuang { 250*2de0c5ccSVictor Chong #if DEBUG 251*2de0c5ccSVictor Chong bl31_params_mem.bl31_ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL; 252*2de0c5ccSVictor Chong #endif 253*2de0c5ccSVictor Chong 25432e9fc1aSHaojian Zhuang return &bl31_params_mem.bl31_ep_info; 25532e9fc1aSHaojian Zhuang } 25632e9fc1aSHaojian Zhuang 25732e9fc1aSHaojian Zhuang void bl2_plat_set_bl31_ep_info(image_info_t *image, 25832e9fc1aSHaojian Zhuang entry_point_info_t *bl31_ep_info) 25932e9fc1aSHaojian Zhuang { 26032e9fc1aSHaojian Zhuang SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); 26132e9fc1aSHaojian Zhuang bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, 26232e9fc1aSHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 26332e9fc1aSHaojian Zhuang } 26432e9fc1aSHaojian Zhuang 2653b6e88a2SVictor Chong /******************************************************************************* 2663b6e88a2SVictor Chong * Before calling this function BL32 is loaded in memory and its entrypoint 2673b6e88a2SVictor Chong * is set by load_image. This is a placeholder for the platform to change 2683b6e88a2SVictor Chong * the entrypoint of BL32 and set SPSR and security state. 2693b6e88a2SVictor Chong * On Hikey we only set the security state of the entrypoint 2703b6e88a2SVictor Chong ******************************************************************************/ 2713b6e88a2SVictor Chong #ifdef BL32_BASE 2723b6e88a2SVictor Chong void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, 2733b6e88a2SVictor Chong entry_point_info_t *bl32_ep_info) 2743b6e88a2SVictor Chong { 2753b6e88a2SVictor Chong SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); 2763b6e88a2SVictor Chong /* 2773b6e88a2SVictor Chong * The Secure Payload Dispatcher service is responsible for 2783b6e88a2SVictor Chong * setting the SPSR prior to entry into the BL32 image. 2793b6e88a2SVictor Chong */ 2803b6e88a2SVictor Chong bl32_ep_info->spsr = 0; 2813b6e88a2SVictor Chong } 2823b6e88a2SVictor Chong 2833b6e88a2SVictor Chong /******************************************************************************* 2843b6e88a2SVictor Chong * Populate the extents of memory available for loading BL32 2853b6e88a2SVictor Chong ******************************************************************************/ 2863b6e88a2SVictor Chong void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) 2873b6e88a2SVictor Chong { 2883b6e88a2SVictor Chong /* 2893b6e88a2SVictor Chong * Populate the extents of memory available for loading BL32. 2903b6e88a2SVictor Chong */ 2913b6e88a2SVictor Chong bl32_meminfo->total_base = BL32_BASE; 2923b6e88a2SVictor Chong bl32_meminfo->free_base = BL32_BASE; 2933b6e88a2SVictor Chong bl32_meminfo->total_size = 2943b6e88a2SVictor Chong (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; 2953b6e88a2SVictor Chong bl32_meminfo->free_size = 2963b6e88a2SVictor Chong (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; 2973b6e88a2SVictor Chong } 2983b6e88a2SVictor Chong #endif /* BL32_BASE */ 2993b6e88a2SVictor Chong 30032e9fc1aSHaojian Zhuang void bl2_plat_set_bl33_ep_info(image_info_t *image, 30132e9fc1aSHaojian Zhuang entry_point_info_t *bl33_ep_info) 30232e9fc1aSHaojian Zhuang { 30332e9fc1aSHaojian Zhuang unsigned long el_status; 30432e9fc1aSHaojian Zhuang unsigned int mode; 30532e9fc1aSHaojian Zhuang 30632e9fc1aSHaojian Zhuang /* Figure out what mode we enter the non-secure world in */ 30732e9fc1aSHaojian Zhuang el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; 30832e9fc1aSHaojian Zhuang el_status &= ID_AA64PFR0_ELX_MASK; 30932e9fc1aSHaojian Zhuang 31032e9fc1aSHaojian Zhuang if (el_status) 31132e9fc1aSHaojian Zhuang mode = MODE_EL2; 31232e9fc1aSHaojian Zhuang else 31332e9fc1aSHaojian Zhuang mode = MODE_EL1; 31432e9fc1aSHaojian Zhuang 31532e9fc1aSHaojian Zhuang /* 31632e9fc1aSHaojian Zhuang * TODO: Consider the possibility of specifying the SPSR in 31732e9fc1aSHaojian Zhuang * the FIP ToC and allowing the platform to have a say as 31832e9fc1aSHaojian Zhuang * well. 31932e9fc1aSHaojian Zhuang */ 32032e9fc1aSHaojian Zhuang bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX, 32132e9fc1aSHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 32232e9fc1aSHaojian Zhuang SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); 32332e9fc1aSHaojian Zhuang } 32432e9fc1aSHaojian Zhuang 32532e9fc1aSHaojian Zhuang void bl2_plat_flush_bl31_params(void) 32632e9fc1aSHaojian Zhuang { 32732e9fc1aSHaojian Zhuang flush_dcache_range((unsigned long)&bl31_params_mem, 32832e9fc1aSHaojian Zhuang sizeof(bl2_to_bl31_params_mem_t)); 32932e9fc1aSHaojian Zhuang } 33032e9fc1aSHaojian Zhuang 33132e9fc1aSHaojian Zhuang void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) 33232e9fc1aSHaojian Zhuang { 33332e9fc1aSHaojian Zhuang bl33_meminfo->total_base = DDR_BASE; 33432e9fc1aSHaojian Zhuang bl33_meminfo->total_size = DDR_SIZE; 33532e9fc1aSHaojian Zhuang bl33_meminfo->free_base = DDR_BASE; 33632e9fc1aSHaojian Zhuang bl33_meminfo->free_size = DDR_SIZE; 33732e9fc1aSHaojian Zhuang } 338*2de0c5ccSVictor Chong #endif /* LOAD_IMAGE_V2 */ 33932e9fc1aSHaojian Zhuang 34032e9fc1aSHaojian Zhuang static void reset_dwmmc_clk(void) 34132e9fc1aSHaojian Zhuang { 34232e9fc1aSHaojian Zhuang unsigned int data; 34332e9fc1aSHaojian Zhuang 34432e9fc1aSHaojian Zhuang /* disable mmc0 bus clock */ 34532e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); 34632e9fc1aSHaojian Zhuang do { 34732e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 34832e9fc1aSHaojian Zhuang } while (data & PERI_CLK0_MMC0); 34932e9fc1aSHaojian Zhuang /* enable mmc0 bus clock */ 35032e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); 35132e9fc1aSHaojian Zhuang do { 35232e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 35332e9fc1aSHaojian Zhuang } while (!(data & PERI_CLK0_MMC0)); 35432e9fc1aSHaojian Zhuang /* reset mmc0 clock domain */ 35532e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); 35632e9fc1aSHaojian Zhuang 35732e9fc1aSHaojian Zhuang /* bypass mmc0 clock phase */ 35832e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL2); 35932e9fc1aSHaojian Zhuang data |= 3; 36032e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL2, data); 36132e9fc1aSHaojian Zhuang 36232e9fc1aSHaojian Zhuang /* disable low power */ 36332e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL13); 36432e9fc1aSHaojian Zhuang data |= 1 << 3; 36532e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL13, data); 36632e9fc1aSHaojian Zhuang do { 36732e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 36832e9fc1aSHaojian Zhuang } while (!(data & PERI_RST0_MMC0)); 36932e9fc1aSHaojian Zhuang 37032e9fc1aSHaojian Zhuang /* unreset mmc0 clock domain */ 37132e9fc1aSHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); 37232e9fc1aSHaojian Zhuang do { 37332e9fc1aSHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 37432e9fc1aSHaojian Zhuang } while (data & PERI_RST0_MMC0); 37532e9fc1aSHaojian Zhuang } 37632e9fc1aSHaojian Zhuang 37732e9fc1aSHaojian Zhuang static void hikey_boardid_init(void) 37832e9fc1aSHaojian Zhuang { 37932e9fc1aSHaojian Zhuang u_register_t midr; 38032e9fc1aSHaojian Zhuang 38132e9fc1aSHaojian Zhuang midr = read_midr(); 38232e9fc1aSHaojian Zhuang mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr); 38332e9fc1aSHaojian Zhuang INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, 38432e9fc1aSHaojian Zhuang (unsigned int)midr); 38532e9fc1aSHaojian Zhuang 38632e9fc1aSHaojian Zhuang mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0); 38732e9fc1aSHaojian Zhuang mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b); 38832e9fc1aSHaojian Zhuang 38932e9fc1aSHaojian Zhuang mmio_write_32(ACPU_ARM64_FLAGA, 0x1234); 39032e9fc1aSHaojian Zhuang mmio_write_32(ACPU_ARM64_FLAGB, 0x5678); 39132e9fc1aSHaojian Zhuang } 39232e9fc1aSHaojian Zhuang 39332e9fc1aSHaojian Zhuang static void hikey_sd_init(void) 39432e9fc1aSHaojian Zhuang { 39532e9fc1aSHaojian Zhuang /* switch pinmux to SD */ 39632e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0); 39732e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0); 39832e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0); 39932e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0); 40032e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0); 40132e9fc1aSHaojian Zhuang mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0); 40232e9fc1aSHaojian Zhuang 40332e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA); 40432e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA); 40532e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA); 40632e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA); 40732e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA); 40832e9fc1aSHaojian Zhuang mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA); 40932e9fc1aSHaojian Zhuang 41032e9fc1aSHaojian Zhuang /* set SD Card detect as nopull */ 41132e9fc1aSHaojian Zhuang mmio_write_32(IOCG_GPIO8, 0); 41232e9fc1aSHaojian Zhuang } 41332e9fc1aSHaojian Zhuang 41432e9fc1aSHaojian Zhuang static void hikey_jumper_init(void) 41532e9fc1aSHaojian Zhuang { 41632e9fc1aSHaojian Zhuang /* set jumper detect as nopull */ 41732e9fc1aSHaojian Zhuang mmio_write_32(IOCG_GPIO24, 0); 41832e9fc1aSHaojian Zhuang /* set jumper detect as GPIO */ 41932e9fc1aSHaojian Zhuang mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0); 42032e9fc1aSHaojian Zhuang } 42132e9fc1aSHaojian Zhuang 42232e9fc1aSHaojian Zhuang void bl2_early_platform_setup(meminfo_t *mem_layout) 42332e9fc1aSHaojian Zhuang { 42432e9fc1aSHaojian Zhuang dw_mmc_params_t params; 42532e9fc1aSHaojian Zhuang 42632e9fc1aSHaojian Zhuang /* Initialize the console to provide early debug support */ 42732e9fc1aSHaojian Zhuang console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 42832e9fc1aSHaojian Zhuang 42932e9fc1aSHaojian Zhuang /* Setup the BL2 memory layout */ 43032e9fc1aSHaojian Zhuang bl2_tzram_layout = *mem_layout; 43132e9fc1aSHaojian Zhuang 43232e9fc1aSHaojian Zhuang /* Clear SRAM since it'll be used by MCU right now. */ 43332e9fc1aSHaojian Zhuang memset((void *)SRAM_BASE, 0, SRAM_SIZE); 43432e9fc1aSHaojian Zhuang 43532e9fc1aSHaojian Zhuang sp804_timer_init(SP804_TIMER0_BASE, 10, 192); 43632e9fc1aSHaojian Zhuang dsb(); 43732e9fc1aSHaojian Zhuang hikey_ddr_init(); 43832e9fc1aSHaojian Zhuang 43932e9fc1aSHaojian Zhuang hikey_boardid_init(); 44032e9fc1aSHaojian Zhuang init_acpu_dvfs(); 44132e9fc1aSHaojian Zhuang hikey_sd_init(); 44232e9fc1aSHaojian Zhuang hikey_jumper_init(); 44332e9fc1aSHaojian Zhuang 44432e9fc1aSHaojian Zhuang reset_dwmmc_clk(); 44532e9fc1aSHaojian Zhuang memset(¶ms, 0, sizeof(dw_mmc_params_t)); 44632e9fc1aSHaojian Zhuang params.reg_base = DWMMC0_BASE; 44732e9fc1aSHaojian Zhuang params.desc_base = HIKEY_MMC_DESC_BASE; 44832e9fc1aSHaojian Zhuang params.desc_size = 1 << 20; 44932e9fc1aSHaojian Zhuang params.clk_rate = 24 * 1000 * 1000; 45032e9fc1aSHaojian Zhuang params.bus_width = EMMC_BUS_WIDTH_8; 45132e9fc1aSHaojian Zhuang params.flags = EMMC_FLAG_CMD23; 45232e9fc1aSHaojian Zhuang dw_mmc_init(¶ms); 45332e9fc1aSHaojian Zhuang 45432e9fc1aSHaojian Zhuang hikey_io_setup(); 45532e9fc1aSHaojian Zhuang } 45632e9fc1aSHaojian Zhuang 45732e9fc1aSHaojian Zhuang void bl2_plat_arch_setup(void) 45832e9fc1aSHaojian Zhuang { 45932e9fc1aSHaojian Zhuang hikey_init_mmu_el1(bl2_tzram_layout.total_base, 46032e9fc1aSHaojian Zhuang bl2_tzram_layout.total_size, 46132e9fc1aSHaojian Zhuang BL2_RO_BASE, 46232e9fc1aSHaojian Zhuang BL2_RO_LIMIT, 46332e9fc1aSHaojian Zhuang BL2_COHERENT_RAM_BASE, 46432e9fc1aSHaojian Zhuang BL2_COHERENT_RAM_LIMIT); 46532e9fc1aSHaojian Zhuang } 46632e9fc1aSHaojian Zhuang 46732e9fc1aSHaojian Zhuang void bl2_platform_setup(void) 46832e9fc1aSHaojian Zhuang { 46932e9fc1aSHaojian Zhuang } 470