17cb09cb4SHaojian Zhuang /* 27cb09cb4SHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 37cb09cb4SHaojian Zhuang * 47cb09cb4SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 57cb09cb4SHaojian Zhuang */ 67cb09cb4SHaojian Zhuang 77cb09cb4SHaojian Zhuang #include <arch_helpers.h> 87cb09cb4SHaojian Zhuang #include <assert.h> 97cb09cb4SHaojian Zhuang #include <bl_common.h> 107cb09cb4SHaojian Zhuang #include <console.h> 117cb09cb4SHaojian Zhuang #include <debug.h> 127cb09cb4SHaojian Zhuang #include <errno.h> 137cb09cb4SHaojian Zhuang #include <generic_delay_timer.h> 147cb09cb4SHaojian Zhuang #include <hi3660.h> 157cb09cb4SHaojian Zhuang #include <mmio.h> 167cb09cb4SHaojian Zhuang #include <platform_def.h> 177cb09cb4SHaojian Zhuang #include <string.h> 187cb09cb4SHaojian Zhuang #include <ufs.h> 197cb09cb4SHaojian Zhuang 207cb09cb4SHaojian Zhuang #include "hikey960_def.h" 217cb09cb4SHaojian Zhuang #include "hikey960_private.h" 227cb09cb4SHaojian Zhuang 237cb09cb4SHaojian Zhuang /* 247cb09cb4SHaojian Zhuang * The next 2 constants identify the extents of the code & RO data region. 257cb09cb4SHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 267cb09cb4SHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 277cb09cb4SHaojian Zhuang * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. 287cb09cb4SHaojian Zhuang */ 297cb09cb4SHaojian Zhuang #define BL2_RO_BASE (unsigned long)(&__RO_START__) 307cb09cb4SHaojian Zhuang #define BL2_RO_LIMIT (unsigned long)(&__RO_END__) 317cb09cb4SHaojian Zhuang 327cb09cb4SHaojian Zhuang /* 337cb09cb4SHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 347cb09cb4SHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 357cb09cb4SHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 367cb09cb4SHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 377cb09cb4SHaojian Zhuang * page-aligned addresses. 387cb09cb4SHaojian Zhuang */ 397cb09cb4SHaojian Zhuang #define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 407cb09cb4SHaojian Zhuang #define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 417cb09cb4SHaojian Zhuang 427cb09cb4SHaojian Zhuang static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); 437cb09cb4SHaojian Zhuang 447cb09cb4SHaojian Zhuang typedef struct bl2_to_bl31_params_mem { 457cb09cb4SHaojian Zhuang bl31_params_t bl31_params; 467cb09cb4SHaojian Zhuang image_info_t bl31_image_info; 477cb09cb4SHaojian Zhuang image_info_t bl32_image_info; 487cb09cb4SHaojian Zhuang image_info_t bl33_image_info; 497cb09cb4SHaojian Zhuang entry_point_info_t bl33_ep_info; 507cb09cb4SHaojian Zhuang entry_point_info_t bl32_ep_info; 517cb09cb4SHaojian Zhuang entry_point_info_t bl31_ep_info; 527cb09cb4SHaojian Zhuang } bl2_to_bl31_params_mem_t; 537cb09cb4SHaojian Zhuang 547cb09cb4SHaojian Zhuang static bl2_to_bl31_params_mem_t bl31_params_mem; 557cb09cb4SHaojian Zhuang 567cb09cb4SHaojian Zhuang meminfo_t *bl2_plat_sec_mem_layout(void) 577cb09cb4SHaojian Zhuang { 587cb09cb4SHaojian Zhuang return &bl2_tzram_layout; 597cb09cb4SHaojian Zhuang } 607cb09cb4SHaojian Zhuang 617cb09cb4SHaojian Zhuang bl31_params_t *bl2_plat_get_bl31_params(void) 627cb09cb4SHaojian Zhuang { 637cb09cb4SHaojian Zhuang bl31_params_t *bl2_to_bl31_params = NULL; 647cb09cb4SHaojian Zhuang 657cb09cb4SHaojian Zhuang /* 667cb09cb4SHaojian Zhuang * Initialise the memory for all the arguments that needs to 677cb09cb4SHaojian Zhuang * be passed to BL3-1 687cb09cb4SHaojian Zhuang */ 697cb09cb4SHaojian Zhuang memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); 707cb09cb4SHaojian Zhuang 717cb09cb4SHaojian Zhuang /* Assign memory for TF related information */ 727cb09cb4SHaojian Zhuang bl2_to_bl31_params = &bl31_params_mem.bl31_params; 737cb09cb4SHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); 747cb09cb4SHaojian Zhuang 757cb09cb4SHaojian Zhuang /* Fill BL3-1 related information */ 767cb09cb4SHaojian Zhuang bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; 777cb09cb4SHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, 787cb09cb4SHaojian Zhuang VERSION_1, 0); 797cb09cb4SHaojian Zhuang 807cb09cb4SHaojian Zhuang /* Fill BL3-2 related information if it exists */ 817cb09cb4SHaojian Zhuang #if BL32_BASE 827cb09cb4SHaojian Zhuang bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; 837cb09cb4SHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, 847cb09cb4SHaojian Zhuang VERSION_1, 0); 857cb09cb4SHaojian Zhuang bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; 867cb09cb4SHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, 877cb09cb4SHaojian Zhuang VERSION_1, 0); 887cb09cb4SHaojian Zhuang #endif 897cb09cb4SHaojian Zhuang 907cb09cb4SHaojian Zhuang /* Fill BL3-3 related information */ 917cb09cb4SHaojian Zhuang bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; 927cb09cb4SHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, 937cb09cb4SHaojian Zhuang PARAM_EP, VERSION_1, 0); 947cb09cb4SHaojian Zhuang 957cb09cb4SHaojian Zhuang /* BL3-3 expects to receive the primary CPU MPID (through x0) */ 967cb09cb4SHaojian Zhuang bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); 977cb09cb4SHaojian Zhuang 987cb09cb4SHaojian Zhuang bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; 997cb09cb4SHaojian Zhuang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, 1007cb09cb4SHaojian Zhuang VERSION_1, 0); 1017cb09cb4SHaojian Zhuang 1027cb09cb4SHaojian Zhuang return bl2_to_bl31_params; 1037cb09cb4SHaojian Zhuang } 1047cb09cb4SHaojian Zhuang 1057cb09cb4SHaojian Zhuang /******************************************************************************* 1067cb09cb4SHaojian Zhuang * Populate the extents of memory available for loading SCP_BL2 (if used), 1077cb09cb4SHaojian Zhuang * i.e. anywhere in trusted RAM as long as it doesn't overwrite BL2. 1087cb09cb4SHaojian Zhuang ******************************************************************************/ 1097cb09cb4SHaojian Zhuang void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo) 1107cb09cb4SHaojian Zhuang { 1117cb09cb4SHaojian Zhuang ufs_params_t ufs_params; 1127cb09cb4SHaojian Zhuang 1137cb09cb4SHaojian Zhuang memset(&ufs_params, 0, sizeof(ufs_params_t)); 1147cb09cb4SHaojian Zhuang ufs_params.reg_base = UFS_REG_BASE; 1157cb09cb4SHaojian Zhuang ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; 1167cb09cb4SHaojian Zhuang ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; 1177cb09cb4SHaojian Zhuang ufs_params.flags = UFS_FLAGS_SKIPINIT; 1187cb09cb4SHaojian Zhuang ufs_init(NULL, &ufs_params); 1197cb09cb4SHaojian Zhuang 1207cb09cb4SHaojian Zhuang hikey960_io_setup(); 1217cb09cb4SHaojian Zhuang 1227cb09cb4SHaojian Zhuang *scp_bl2_meminfo = bl2_tzram_layout; 1237cb09cb4SHaojian Zhuang } 1247cb09cb4SHaojian Zhuang 1257cb09cb4SHaojian Zhuang extern int load_lpm3(void); 1267cb09cb4SHaojian Zhuang 1277cb09cb4SHaojian Zhuang int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) 1287cb09cb4SHaojian Zhuang { 1297cb09cb4SHaojian Zhuang int i; 1307cb09cb4SHaojian Zhuang int *buf; 1317cb09cb4SHaojian Zhuang 1327cb09cb4SHaojian Zhuang assert(scp_bl2_image_info->image_size < SCP_MEM_SIZE); 1337cb09cb4SHaojian Zhuang 1347cb09cb4SHaojian Zhuang INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); 1357cb09cb4SHaojian Zhuang 1367cb09cb4SHaojian Zhuang INFO("BL2: SCP_BL2: 0x%lx@0x%x\n", 1377cb09cb4SHaojian Zhuang scp_bl2_image_info->image_base, 1387cb09cb4SHaojian Zhuang scp_bl2_image_info->image_size); 1397cb09cb4SHaojian Zhuang 1407cb09cb4SHaojian Zhuang buf = (int *)scp_bl2_image_info->image_base; 1417cb09cb4SHaojian Zhuang 1427cb09cb4SHaojian Zhuang INFO("BL2: SCP_BL2 HEAD:\n"); 1437cb09cb4SHaojian Zhuang for (i = 0; i < 64; i += 4) 1447cb09cb4SHaojian Zhuang INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", 1457cb09cb4SHaojian Zhuang buf[i], buf[i+1], buf[i+2], buf[i+3]); 1467cb09cb4SHaojian Zhuang 1477cb09cb4SHaojian Zhuang buf = (int *)(scp_bl2_image_info->image_base + 1487cb09cb4SHaojian Zhuang scp_bl2_image_info->image_size - 256); 1497cb09cb4SHaojian Zhuang 1507cb09cb4SHaojian Zhuang INFO("BL2: SCP_BL2 TAIL:\n"); 1517cb09cb4SHaojian Zhuang for (i = 0; i < 64; i += 4) 1527cb09cb4SHaojian Zhuang INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", 1537cb09cb4SHaojian Zhuang buf[i], buf[i+1], buf[i+2], buf[i+3]); 1547cb09cb4SHaojian Zhuang 1557cb09cb4SHaojian Zhuang memcpy((void *)SCP_MEM_BASE, 1567cb09cb4SHaojian Zhuang (void *)scp_bl2_image_info->image_base, 1577cb09cb4SHaojian Zhuang scp_bl2_image_info->image_size); 1587cb09cb4SHaojian Zhuang 1597cb09cb4SHaojian Zhuang INFO("BL2: SCP_BL2 transferred to SCP\n"); 1607cb09cb4SHaojian Zhuang 1617cb09cb4SHaojian Zhuang load_lpm3(); 1627cb09cb4SHaojian Zhuang (void)buf; 1637cb09cb4SHaojian Zhuang 1647cb09cb4SHaojian Zhuang return 0; 1657cb09cb4SHaojian Zhuang } 1667cb09cb4SHaojian Zhuang 1677cb09cb4SHaojian Zhuang struct entry_point_info *bl2_plat_get_bl31_ep_info(void) 1687cb09cb4SHaojian Zhuang { 1697cb09cb4SHaojian Zhuang return &bl31_params_mem.bl31_ep_info; 1707cb09cb4SHaojian Zhuang } 1717cb09cb4SHaojian Zhuang 1727cb09cb4SHaojian Zhuang void bl2_plat_set_bl31_ep_info(image_info_t *image, 1737cb09cb4SHaojian Zhuang entry_point_info_t *bl31_ep_info) 1747cb09cb4SHaojian Zhuang { 1757cb09cb4SHaojian Zhuang SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); 1767cb09cb4SHaojian Zhuang bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, 1777cb09cb4SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 1787cb09cb4SHaojian Zhuang } 1797cb09cb4SHaojian Zhuang 180*5e3325e7SVictor Chong /******************************************************************************* 181*5e3325e7SVictor Chong * Before calling this function BL32 is loaded in memory and its entrypoint 182*5e3325e7SVictor Chong * is set by load_image. This is a placeholder for the platform to change 183*5e3325e7SVictor Chong * the entrypoint of BL32 and set SPSR and security state. 184*5e3325e7SVictor Chong * On Hikey we only set the security state of the entrypoint 185*5e3325e7SVictor Chong ******************************************************************************/ 186*5e3325e7SVictor Chong #ifdef BL32_BASE 187*5e3325e7SVictor Chong void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, 188*5e3325e7SVictor Chong entry_point_info_t *bl32_ep_info) 189*5e3325e7SVictor Chong { 190*5e3325e7SVictor Chong SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); 191*5e3325e7SVictor Chong /* 192*5e3325e7SVictor Chong * The Secure Payload Dispatcher service is responsible for 193*5e3325e7SVictor Chong * setting the SPSR prior to entry into the BL32 image. 194*5e3325e7SVictor Chong */ 195*5e3325e7SVictor Chong bl32_ep_info->spsr = 0; 196*5e3325e7SVictor Chong } 197*5e3325e7SVictor Chong 198*5e3325e7SVictor Chong /******************************************************************************* 199*5e3325e7SVictor Chong * Populate the extents of memory available for loading BL32 200*5e3325e7SVictor Chong ******************************************************************************/ 201*5e3325e7SVictor Chong void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) 202*5e3325e7SVictor Chong { 203*5e3325e7SVictor Chong /* 204*5e3325e7SVictor Chong * Populate the extents of memory available for loading BL32. 205*5e3325e7SVictor Chong */ 206*5e3325e7SVictor Chong bl32_meminfo->total_base = BL32_BASE; 207*5e3325e7SVictor Chong bl32_meminfo->free_base = BL32_BASE; 208*5e3325e7SVictor Chong bl32_meminfo->total_size = 209*5e3325e7SVictor Chong (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; 210*5e3325e7SVictor Chong bl32_meminfo->free_size = 211*5e3325e7SVictor Chong (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; 212*5e3325e7SVictor Chong } 213*5e3325e7SVictor Chong #endif /* BL32_BASE */ 214*5e3325e7SVictor Chong 2157cb09cb4SHaojian Zhuang void bl2_plat_set_bl33_ep_info(image_info_t *image, 2167cb09cb4SHaojian Zhuang entry_point_info_t *bl33_ep_info) 2177cb09cb4SHaojian Zhuang { 2187cb09cb4SHaojian Zhuang unsigned long el_status; 2197cb09cb4SHaojian Zhuang unsigned int mode; 2207cb09cb4SHaojian Zhuang 2217cb09cb4SHaojian Zhuang /* Figure out what mode we enter the non-secure world in */ 2227cb09cb4SHaojian Zhuang el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; 2237cb09cb4SHaojian Zhuang el_status &= ID_AA64PFR0_ELX_MASK; 2247cb09cb4SHaojian Zhuang 2257cb09cb4SHaojian Zhuang if (el_status) 2267cb09cb4SHaojian Zhuang mode = MODE_EL2; 2277cb09cb4SHaojian Zhuang else 2287cb09cb4SHaojian Zhuang mode = MODE_EL1; 2297cb09cb4SHaojian Zhuang 2307cb09cb4SHaojian Zhuang /* 2317cb09cb4SHaojian Zhuang * TODO: Consider the possibility of specifying the SPSR in 2327cb09cb4SHaojian Zhuang * the FIP ToC and allowing the platform to have a say as 2337cb09cb4SHaojian Zhuang * well. 2347cb09cb4SHaojian Zhuang */ 2357cb09cb4SHaojian Zhuang bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX, 2367cb09cb4SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 2377cb09cb4SHaojian Zhuang SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); 2387cb09cb4SHaojian Zhuang } 2397cb09cb4SHaojian Zhuang 2407cb09cb4SHaojian Zhuang void bl2_plat_flush_bl31_params(void) 2417cb09cb4SHaojian Zhuang { 2427cb09cb4SHaojian Zhuang flush_dcache_range((unsigned long)&bl31_params_mem, 2437cb09cb4SHaojian Zhuang sizeof(bl2_to_bl31_params_mem_t)); 2447cb09cb4SHaojian Zhuang } 2457cb09cb4SHaojian Zhuang 2467cb09cb4SHaojian Zhuang void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) 2477cb09cb4SHaojian Zhuang { 2487cb09cb4SHaojian Zhuang bl33_meminfo->total_base = DDR_BASE; 2497cb09cb4SHaojian Zhuang bl33_meminfo->total_size = DDR_SIZE; 2507cb09cb4SHaojian Zhuang bl33_meminfo->free_base = DDR_BASE; 2517cb09cb4SHaojian Zhuang bl33_meminfo->free_size = DDR_SIZE; 2527cb09cb4SHaojian Zhuang } 2537cb09cb4SHaojian Zhuang 2547cb09cb4SHaojian Zhuang void bl2_early_platform_setup(meminfo_t *mem_layout) 2557cb09cb4SHaojian Zhuang { 2567cb09cb4SHaojian Zhuang unsigned int id, uart_base; 2577cb09cb4SHaojian Zhuang 2587cb09cb4SHaojian Zhuang generic_delay_timer_init(); 2597cb09cb4SHaojian Zhuang hikey960_read_boardid(&id); 2607cb09cb4SHaojian Zhuang if (id == 5300) 2617cb09cb4SHaojian Zhuang uart_base = PL011_UART5_BASE; 2627cb09cb4SHaojian Zhuang else 2637cb09cb4SHaojian Zhuang uart_base = PL011_UART6_BASE; 2647cb09cb4SHaojian Zhuang 2657cb09cb4SHaojian Zhuang /* Initialize the console to provide early debug support */ 2667cb09cb4SHaojian Zhuang console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 2677cb09cb4SHaojian Zhuang 2687cb09cb4SHaojian Zhuang /* Setup the BL2 memory layout */ 2697cb09cb4SHaojian Zhuang bl2_tzram_layout = *mem_layout; 2707cb09cb4SHaojian Zhuang } 2717cb09cb4SHaojian Zhuang 2727cb09cb4SHaojian Zhuang void bl2_plat_arch_setup(void) 2737cb09cb4SHaojian Zhuang { 2747cb09cb4SHaojian Zhuang hikey960_init_mmu_el1(bl2_tzram_layout.total_base, 2757cb09cb4SHaojian Zhuang bl2_tzram_layout.total_size, 2767cb09cb4SHaojian Zhuang BL2_RO_BASE, 2777cb09cb4SHaojian Zhuang BL2_RO_LIMIT, 2787cb09cb4SHaojian Zhuang BL2_COHERENT_RAM_BASE, 2797cb09cb4SHaojian Zhuang BL2_COHERENT_RAM_LIMIT); 2807cb09cb4SHaojian Zhuang } 2817cb09cb4SHaojian Zhuang 2827cb09cb4SHaojian Zhuang void bl2_platform_setup(void) 2837cb09cb4SHaojian Zhuang { 2847cb09cb4SHaojian Zhuang /* disable WDT0 */ 2857cb09cb4SHaojian Zhuang if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) { 2867cb09cb4SHaojian Zhuang mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK); 2877cb09cb4SHaojian Zhuang mmio_write_32(WDT0_REG_BASE + WDT_CONTROL_OFFSET, 0); 2887cb09cb4SHaojian Zhuang mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, 0); 2897cb09cb4SHaojian Zhuang } 2907cb09cb4SHaojian Zhuang } 291