diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
commit | be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b (patch) | |
tree | 779c248fb61c83f65d1f0dc867f2053d76b4e03a /plat/hisilicon | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream.tar.xz arm-trusted-firmware-upstream.zip |
Adding upstream version 2.10.0+dfsg.upstream/2.10.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
86 files changed, 14531 insertions, 0 deletions
diff --git a/plat/hisilicon/hikey/aarch64/hikey_common.c b/plat/hisilicon/hikey/aarch64/hikey_common.c new file mode 100644 index 0000000..702fc2d --- /dev/null +++ b/plat/hisilicon/hikey/aarch64/hikey_common.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables.h> +#include <plat/common/platform.h> + +#include <hikey_def.h> +#include <hikey_layout.h> + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE - DDR_SEC_SIZE, \ + MT_DEVICE | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_ROM_PARAM MAP_REGION_FLAT(XG2RAM0_BASE, \ + BL1_XG2RAM0_OFFSET, \ + MT_DEVICE | MT_RO | MT_SECURE) + +#define MAP_SRAM MAP_REGION_FLAT(SRAM_BASE, \ + SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * BL1 needs to access the areas of MMC_SRAM. + * BL1 loads BL2 from eMMC into SRAM before DDR initialized. + */ +#define MAP_MMC_SRAM MAP_REGION_FLAT(HIKEY_BL1_MMC_DESC_BASE, \ + HIKEY_BL1_MMC_DESC_SIZE + \ + HIKEY_BL1_MMC_DATA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * hikey_init_mmu_elx() will give the available subset of that, + */ +#ifdef IMAGE_BL1 +static const mmap_region_t hikey_mmap[] = { + MAP_DEVICE, + MAP_ROM_PARAM, + MAP_MMC_SRAM, + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t hikey_mmap[] = { + MAP_DDR, + MAP_DEVICE, + MAP_TSP_MEM, + MAP_SRAM, + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t hikey_mmap[] = { + MAP_DEVICE, + MAP_SRAM, + MAP_TSP_MEM, + {0} +}; +#endif + +#ifdef IMAGE_BL32 +static const mmap_region_t hikey_mmap[] = { + MAP_DEVICE, + MAP_DDR, + {0} +}; +#endif + +/* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + */ +#define HIKEY_CONFIGURE_MMU_EL(_el) \ + void hikey_init_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(hikey_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +HIKEY_CONFIGURE_MMU_EL(1) +HIKEY_CONFIGURE_MMU_EL(3) + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return HIKEY_NS_IMAGE_OFFSET; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return 1200000; +} diff --git a/plat/hisilicon/hikey/aarch64/hikey_helpers.S b/plat/hisilicon/hikey/aarch64/hikey_helpers.S new file mode 100644 index 0000000..82a404a --- /dev/null +++ b/plat/hisilicon/hikey/aarch64/hikey_helpers.S @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <hikey_def.h> + + .globl plat_my_core_pos + .globl platform_mem_init + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_report_exception + .globl plat_reset_handler + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on HIKEY. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, CRASH_CONSOLE_BASE + mov_imm x1, PL011_UART_CLK_IN_HZ + mov_imm x2, PL011_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, CRASH_CONSOLE_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On HIKEY platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mov x8, x30 + + /* Turn on LED according to x0 (0 -- f) */ + ldr x2, =0xf7020000 + and x1, x0, #1 + str w1, [x2, #4] + and x1, x0, #2 + str w1, [x2, #8] + and x1, x0, #4 + str w1, [x2, #16] + and x1, x0, #8 + str w1, [x2, #32] + + mrs x2, currentel + and x2, x2, #0xc0 + /* Check EL1 */ + cmp x2, #0x04 + beq plat_report_el1 + + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el3_str + bl asm_print_str + + mrs x4, esr_el3 + bl asm_print_hex + + adr x4, elr_el3_str + bl asm_print_str + + mrs x4, elr_el3 + bl asm_print_hex + b plat_report_end + +plat_report_el1: + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el1_str + bl asm_print_str + + mrs x4, esr_el1 + bl asm_print_hex + + adr x4, elr_el1_str + bl asm_print_str + + mrs x4, elr_el1 + bl asm_print_hex +plat_report_end: + mov x30, x8 + ret +endfunc plat_report_exception + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler + +.section .rodata.rev_err_str, "aS" +plat_err_str: + .asciz "\nPlatform exception reporting:" +esr_el3_str: + .asciz "\nESR_EL3: " +elr_el3_str: + .asciz "\nELR_EL3: " +esr_el1_str: + .asciz "\nESR_EL1: " +elr_el1_str: + .asciz "\nELR_EL1: " diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c new file mode 100644 index 0000000..31ff820 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_bl1_setup.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <stdint.h> +#include <string.h> + +#include <arch_helpers.h> +#include <bl1/tbbr/tbbr_img_desc.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/arm/pl011.h> +#include <drivers/mmc.h> +#include <drivers/synopsys/dw_mmc.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <hi6220.h> +#include <hikey_def.h> +#include <hikey_layout.h> + +#include "hikey_private.h" + +/* Data structure which holds the extents of the trusted RAM for BL1 */ +static meminfo_t bl1_tzram_layout; +static console_t console; +static struct mmc_device_info mmc_info; + +enum { + BOOT_NORMAL = 0, + BOOT_USB_DOWNLOAD, + BOOT_UART_DOWNLOAD, +}; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/* + * Perform any BL1 specific platform actions. + */ +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL1_RW_BASE; + bl1_tzram_layout.total_size = BL1_RW_SIZE; + + INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ +} + +/* + * Perform the very early platform specific architecture setup here. At the + * moment this only does basic initialization. Later architectural setup + * (bl1_arch_setup()) does not do anything platform specific. + */ +void bl1_plat_arch_setup(void) +{ + hikey_init_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL1_RO_BASE, + BL1_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +/* + * Function which will perform any remaining platform-specific setup that can + * occur after the MMU and data cache have been enabled. + */ +void bl1_platform_setup(void) +{ + dw_mmc_params_t params; + + assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) && + ((SRAM_BASE + SRAM_SIZE) >= + (HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE))); + hikey_sp804_init(); + hikey_gpio_init(); + hikey_pmussi_init(); + hikey_hi6553_init(); + + hikey_rtc_init(); + + hikey_mmc_pll_init(); + + memset(¶ms, 0, sizeof(dw_mmc_params_t)); + params.reg_base = DWMMC0_BASE; + params.desc_base = HIKEY_BL1_MMC_DESC_BASE; + params.desc_size = 1 << 20; + params.clk_rate = 24 * 1000 * 1000; + params.bus_width = MMC_BUS_WIDTH_8; + params.flags = MMC_FLAG_CMD23; + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); + + hikey_io_setup(); +} + +/* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or not. + */ +unsigned int bl1_plat_get_next_image_id(void) +{ + int32_t boot_mode; + unsigned int ret; + + boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE); + switch (boot_mode) { + case BOOT_USB_DOWNLOAD: + case BOOT_UART_DOWNLOAD: + ret = NS_BL1U_IMAGE_ID; + break; + default: + WARN("Invalid boot mode is found:%d\n", boot_mode); + panic(); + } + return ret; +} + +image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +{ + unsigned int index = 0; + + while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { + if (bl1_tbbr_image_descs[index].image_id == image_id) + return &bl1_tbbr_image_descs[index]; + + index++; + } + + return NULL; +} + +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + uint64_t data = 0; + + if (image_id == BL2_IMAGE_ID) + panic(); + inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); + __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); + do { + data |= 3 << 20; + __asm__ volatile ("msr cpacr_el1, %0" : : "r"(data)); + __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); + } while ((data & (3 << 20)) != (3 << 20)); + INFO("cpacr_el1:0x%" PRIx64 "\n", data); + + ep_info->args.arg0 = 0xffff & read_mpidr(); + ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} diff --git a/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c b/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c new file mode 100644 index 0000000..d029703 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> /* also includes hikey_def.h and hikey_layout.h*/ + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + +#else /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager + * image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged + * image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = HIKEY_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = HIKEY_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = HIKEY_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = HIKEY_NS_IMAGE_OFFSET, + .image_info.image_max_size = 0x200000 /* 2MB */, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c new file mode 100644 index 0000000..a90f12c --- /dev/null +++ b/plat/hisilicon/hikey/hikey_bl2_setup.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <platform_def.h> /* also includes hikey_def.h and hikey_layout.h*/ + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/arm/pl011.h> +#include <drivers/delay_timer.h> +#include <drivers/mmc.h> +#include <drivers/synopsys/dw_mmc.h> +#include <lib/mmio.h> +#ifdef SPD_opteed +#include <lib/optee_utils.h> +#endif +#include <plat/common/platform.h> + +#include <hi6220.h> +#include <hisi_mcu.h> +#include <hisi_sram_map.h> +#include "hikey_private.h" + +#define BL2_RW_BASE (BL_CODE_END) + +static meminfo_t bl2_el3_tzram_layout; +static console_t console; +static struct mmc_device_info mmc_info; + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + /* Enable MCU SRAM */ + hisi_mcu_enable_sram(); + + /* Load MCU binary into SRAM */ + hisi_mcu_load_image(scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + /* Let MCU running */ + hisi_mcu_start_run(); + + INFO("%s: MCU PC is at 0x%x\n", + __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2)); + INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n", + __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4)); + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t hikey_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t hikey_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +uint32_t hikey_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + return hikey_set_fip_addr(image_id, "fastboot"); +} + +int hikey_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + assert(bl_mem_params); + + switch (image_id) { +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } +#endif + bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return hikey_bl2_handle_post_image_load(image_id); +} + +static void reset_dwmmc_clk(void) +{ + unsigned int data; + + /* disable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC0); + /* enable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC0)); + /* reset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); + + /* bypass mmc0 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 3; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC0)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC0); +} + +static void hikey_boardid_init(void) +{ + u_register_t midr; + + midr = read_midr(); + mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr); + INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, + (unsigned int)midr); + + mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0); + mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b); + + mmio_write_32(ACPU_ARM64_FLAGA, 0x1234); + mmio_write_32(ACPU_ARM64_FLAGB, 0x5678); +} + +static void hikey_sd_init(void) +{ + /* switch pinmux to SD */ + mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0); + + mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA); + mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA); + + /* set SD Card detect as nopull */ + mmio_write_32(IOCG_GPIO8, 0); +} + +static void hikey_jumper_init(void) +{ + /* set jumper detect as nopull */ + mmio_write_32(IOCG_GPIO24, 0); + /* set jumper detect as GPIO */ + mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + /* Initialize the console to provide early debug support */ + console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + /* + * Allow BL2 to see the whole Trusted RAM. + */ + bl2_el3_tzram_layout.total_base = BL2_RW_BASE; + bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE; +} + +void bl2_el3_plat_arch_setup(void) +{ + hikey_init_mmu_el3(bl2_el3_tzram_layout.total_base, + bl2_el3_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl2_platform_setup(void) +{ + dw_mmc_params_t params; + + hikey_sp804_init(); + hikey_gpio_init(); + hikey_pmussi_init(); + hikey_hi6553_init(); + /* Clear SRAM since it'll be used by MCU right now. */ + memset((void *)SRAM_BASE, 0, SRAM_SIZE); + + dsb(); + hikey_ddr_init(DDR_FREQ_800M); + hikey_security_setup(); + + hikey_boardid_init(); + init_acpu_dvfs(); + hikey_rtc_init(); + hikey_sd_init(); + hikey_jumper_init(); + + hikey_mmc_pll_init(); + + /* Clean SRAM before MCU used */ + clean_dcache_range(SRAM_BASE, SRAM_SIZE); + + reset_dwmmc_clk(); + memset(¶ms, 0, sizeof(dw_mmc_params_t)); + params.reg_base = DWMMC0_BASE; + params.desc_base = HIKEY_MMC_DESC_BASE; + params.desc_size = 1 << 20; + params.clk_rate = 24 * 1000 * 1000; + params.bus_width = MMC_BUS_WIDTH_8; + params.flags = MMC_FLAG_CMD23; + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); + + hikey_io_setup(); +} diff --git a/plat/hisilicon/hikey/hikey_bl31_setup.c b/plat/hisilicon/hikey/hikey_bl31_setup.c new file mode 100644 index 0000000..7d008e7 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_bl31_setup.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/interrupt_props.h> +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/pl011.h> +#include <lib/mmio.h> + +#include <hi6220.h> +#include <hikey_def.h> +#include <hisi_ipc.h> +#include <hisi_pwrc.h> + +#include "hikey_private.h" + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; +static console_t console; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +/* + * Ideally `arm_gic_data` structure definition should be a `const` but it is + * kept as modifiable for overwriting with different GICD and GICC base when + * running on FVP with VE memory map. + */ +gicv2_driver_data_t hikey_gic_data = { + .gicd_base = PLAT_ARM_GICD_BASE, + .gicc_base = PLAT_ARM_GICC_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +static const int cci_map[] = { + CCI400_SL_IFACE3_CLUSTER_IX, + CCI400_SL_IFACE4_CLUSTER_IX +}; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + void *from_bl2; + + from_bl2 = (void *) arg0; + + /* Initialize the console to provide early debug support */ + console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Initialize CCI driver */ + cci_init(CCI400_BASE, cci_map, ARRAY_SIZE(cci_map)); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_ep_info.pc == 0) + panic(); +} + +void bl31_plat_arch_setup(void) +{ + hikey_init_mmu_el3(BL31_BASE, + BL31_LIMIT - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +/* Initialize EDMAC controller with non-secure mode. */ +static void hikey_edma_init(void) +{ + int i; + uint32_t non_secure; + + non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC; + mmio_write_32(EDMAC_SEC_CTRL, non_secure); + + for (i = 0; i < EDMAC_CHANNEL_NUMS; i++) { + mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18)); + } +} + +void bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + hikey_edma_init(); + + hisi_ipc_init(); + hisi_pwrc_setup(); +} + +void bl31_plat_runtime_setup(void) +{ +} diff --git a/plat/hisilicon/hikey/hikey_bl_common.c b/plat/hisilicon/hikey/hikey_bl_common.c new file mode 100644 index 0000000..d062de4 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_bl_common.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <drivers/arm/pl061_gpio.h> +#include <drivers/arm/sp804_delay_timer.h> +#include <drivers/gpio.h> +#include <lib/mmio.h> + +#include <hi6220.h> +#include <hi6553.h> +#include "hikey_private.h" + +void hikey_sp804_init(void) +{ + uint32_t data; + + /* select the clock of dual timer0 */ + data = mmio_read_32(AO_SC_TIMER_EN0); + while (data & 3) { + data &= ~3; + data |= 3 << 16; + mmio_write_32(AO_SC_TIMER_EN0, data); + data = mmio_read_32(AO_SC_TIMER_EN0); + } + /* enable the pclk of dual timer0 */ + data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); + while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) { + mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0); + data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); + } + /* reset dual timer0 */ + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0); + do { + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)); + /* unreset dual timer0 */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0); + do { + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0)); + + sp804_timer_init(SP804_TIMER0_BASE, 10, 192); +} + +void hikey_gpio_init(void) +{ + pl061_gpio_init(); + pl061_gpio_register(GPIO0_BASE, 0); + pl061_gpio_register(GPIO1_BASE, 1); + pl061_gpio_register(GPIO2_BASE, 2); + pl061_gpio_register(GPIO3_BASE, 3); + pl061_gpio_register(GPIO4_BASE, 4); + pl061_gpio_register(GPIO5_BASE, 5); + pl061_gpio_register(GPIO6_BASE, 6); + pl061_gpio_register(GPIO7_BASE, 7); + pl061_gpio_register(GPIO8_BASE, 8); + pl061_gpio_register(GPIO9_BASE, 9); + pl061_gpio_register(GPIO10_BASE, 10); + pl061_gpio_register(GPIO11_BASE, 11); + pl061_gpio_register(GPIO12_BASE, 12); + pl061_gpio_register(GPIO13_BASE, 13); + pl061_gpio_register(GPIO14_BASE, 14); + pl061_gpio_register(GPIO15_BASE, 15); + pl061_gpio_register(GPIO16_BASE, 16); + pl061_gpio_register(GPIO17_BASE, 17); + pl061_gpio_register(GPIO18_BASE, 18); + pl061_gpio_register(GPIO19_BASE, 19); + + /* Power on indicator LED (USER_LED1). */ + gpio_set_direction(32, GPIO_DIR_OUT); /* LED1 */ + gpio_set_value(32, GPIO_LEVEL_HIGH); + gpio_set_direction(33, GPIO_DIR_OUT); /* LED2 */ + gpio_set_value(33, GPIO_LEVEL_LOW); + gpio_set_direction(34, GPIO_DIR_OUT); /* LED3 */ + gpio_set_direction(35, GPIO_DIR_OUT); /* LED4 */ +} + +void hikey_pmussi_init(void) +{ + uint32_t data; + + /* Initialize PWR_HOLD GPIO */ + gpio_set_direction(0, GPIO_DIR_OUT); + gpio_set_value(0, GPIO_LEVEL_LOW); + + /* + * After reset, PMUSSI stays in reset mode. + * Now make it out of reset. + */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); + do { + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + } while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); + + /* Set PMUSSI clock latency for read operation. */ + data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3); + data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK; + data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3; + mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data); + + /* enable PMUSSI clock */ + data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU | + AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU; + mmio_write_32(AO_SC_PERIPH_CLKEN5, data); + data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI; + mmio_write_32(AO_SC_PERIPH_CLKEN4, data); + + gpio_set_value(0, GPIO_LEVEL_HIGH); +} + +void hikey_hi6553_init(void) +{ + uint8_t data; + + mmio_write_8(HI6553_PERI_EN_MARK, 0x1e); + mmio_write_8(HI6553_NP_REG_ADJ1, 0); + data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC | + DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2; + mmio_write_8(HI6553_DISABLE6_XO_CLK, data); + + /* configure BUCK0 & BUCK1 */ + mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e); + mmio_write_8(HI6553_BUCK0_CTRL7, 0x10); + mmio_write_8(HI6553_BUCK1_CTRL7, 0x10); + mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e); + mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e); + mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc); + mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc); + + /* configure BUCK2 */ + mmio_write_8(HI6553_BUCK2_REG1, 0x4f); + mmio_write_8(HI6553_BUCK2_REG5, 0x99); + mmio_write_8(HI6553_BUCK2_REG6, 0x45); + mdelay(1); + mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22); + mdelay(1); + + /* configure BUCK3 */ + mmio_write_8(HI6553_BUCK3_REG3, 0x02); + mmio_write_8(HI6553_BUCK3_REG5, 0x99); + mmio_write_8(HI6553_BUCK3_REG6, 0x41); + mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02); + mdelay(1); + + /* configure BUCK4 */ + mmio_write_8(HI6553_BUCK4_REG2, 0x9a); + mmio_write_8(HI6553_BUCK4_REG5, 0x99); + mmio_write_8(HI6553_BUCK4_REG6, 0x45); + + /* configure LDO20 */ + mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50); + + mmio_write_8(HI6553_NP_REG_CHG, 0x0f); + mmio_write_8(HI6553_CLK_TOP0, 0x06); + mmio_write_8(HI6553_CLK_TOP3, 0xc0); + mmio_write_8(HI6553_CLK_TOP4, 0x00); + + /* configure LDO7 & LDO10 for SD slot */ + /* enable LDO7 */ + data = mmio_read_8(HI6553_LDO7_REG_ADJ); + data = (data & 0xf8) | 0x2; + mmio_write_8(HI6553_LDO7_REG_ADJ, data); + mdelay(5); + mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6); + mdelay(5); + /* enable LDO10 */ + data = mmio_read_8(HI6553_LDO10_REG_ADJ); + data = (data & 0xf8) | 0x5; + mmio_write_8(HI6553_LDO10_REG_ADJ, data); + mdelay(5); + mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1); + mdelay(5); + /* enable LDO15 */ + data = mmio_read_8(HI6553_LDO15_REG_ADJ); + data = (data & 0xf8) | 0x4; + mmio_write_8(HI6553_LDO15_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6); + mdelay(5); + /* enable LDO19 */ + data = mmio_read_8(HI6553_LDO19_REG_ADJ); + data |= 0x7; + mmio_write_8(HI6553_LDO19_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2); + mdelay(5); + /* enable LDO21 */ + data = mmio_read_8(HI6553_LDO21_REG_ADJ); + data = (data & 0xf8) | 0x3; + mmio_write_8(HI6553_LDO21_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4); + mdelay(5); + /* enable LDO22 */ + data = mmio_read_8(HI6553_LDO22_REG_ADJ); + data = (data & 0xf8) | 0x7; + mmio_write_8(HI6553_LDO22_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5); + mdelay(5); + + /* select 32.764KHz */ + mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01); + + /* Disable vbus_det interrupts */ + data = mmio_read_8(HI6553_IRQ2_MASK); + data = data | 0x3; + mmio_write_8(HI6553_IRQ2_MASK, data); +} + +void init_mmc0_pll(void) +{ + unsigned int data; + + /* select SYSPLL as the source of MMC0 */ + /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (!(data & (1 << 5))); + /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (data & (1 << 13)); + + mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0)); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & (1 << 0))); + + data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); + data |= 1 << 1; + mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); + + do { + mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb); + data = mmio_read_32(PERI_SC_CLKCFG8BIT1); + } while ((data & 0xb) != 0xb); +} + +void reset_mmc0_clk(void) +{ + unsigned int data; + + /* disable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC0); + /* enable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC0)); + /* reset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); + + /* bypass mmc0 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 3; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC0)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC0); +} + +void init_media_clk(void) +{ + unsigned int data, value; + + data = mmio_read_32(PMCTRL_MEDPLLCTRL); + data |= 1; + mmio_write_32(PMCTRL_MEDPLLCTRL, data); + + for (;;) { + data = mmio_read_32(PMCTRL_MEDPLLCTRL); + value = 1 << 28; + if ((data & value) == value) + break; + } + + data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); + data = 1 << 10; + mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); +} + +void init_mmc1_pll(void) +{ + uint32_t data; + + /* select SYSPLL as the source of MMC1 */ + /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (!(data & (1 << 11))); + /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (data & (1 << 14)); + + mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1)); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & (1 << 1))); + + data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); + data |= 1 << 2; + mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); + + do { + /* 1.2GHz / 50 = 24MHz */ + mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7)); + data = mmio_read_32(PERI_SC_CLKCFG8BIT2); + } while ((data & 0x31) != 0x31); +} + +void reset_mmc1_clk(void) +{ + unsigned int data; + + /* disable mmc1 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC1); + /* enable mmc1 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC1)); + /* reset mmc1 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1); + + /* bypass mmc1 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3 << 2; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 4; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC1)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC1); +} + +/* Initialize PLL of both eMMC and SD controllers. */ +void hikey_mmc_pll_init(void) +{ + init_mmc0_pll(); + reset_mmc0_clk(); + init_media_clk(); + + dsb(); + + init_mmc1_pll(); + reset_mmc1_clk(); +} + +void hikey_rtc_init(void) +{ + uint32_t data; + + data = mmio_read_32(AO_SC_PERIPH_CLKEN4); + data |= AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N; + mmio_write_32(AO_SC_PERIPH_CLKEN4, data); +} diff --git a/plat/hisilicon/hikey/hikey_ddr.c b/plat/hisilicon/hikey/hikey_ddr.c new file mode 100644 index 0000000..cd9e9a2 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_ddr.c @@ -0,0 +1,1451 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/sp804_delay_timer.h> +#include <lib/mmio.h> + +#include <hi6220.h> +#include <hi6553.h> +#include <hisi_sram_map.h> +#include "hikey_private.h" + +static void init_pll(void) +{ + unsigned int data; + + data = mmio_read_32((0xf7032000 + 0x000)); + data |= 0x1; + mmio_write_32((0xf7032000 + 0x000), data); + do { + data = mmio_read_32((0xf7032000 + 0x000)); + } while (!(data & (1 << 28))); + + data = mmio_read_32((0xf7800000 + 0x000)); + data &= ~0x007; + data |= 0x004; + mmio_write_32((0xf7800000 + 0x000), data); + do { + data = mmio_read_32((0xf7800000 + 0x014)); + data &= 0x007; + } while (data != 0x004); + + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201); + dsb(); + isb(); + udelay(10); + mmio_write_32(0xf7032000 + 0x02c, 0x5110103e); + dsb(); + isb(); + udelay(10); + data = mmio_read_32(0xf7032000 + 0x050); + data |= 1 << 28; + mmio_write_32(0xf7032000 + 0x050, data); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201); + dsb(); + isb(); + udelay(10); +} + +static void init_freq(void) +{ + unsigned int data, tmp; + unsigned int cpuext_cfg, ddr_cfg; + + mmio_write_32((0xf7032000 + 0x374), 0x4a); + mmio_write_32((0xf7032000 + 0x368), 0xda); + mmio_write_32((0xf7032000 + 0x36c), 0x01); + mmio_write_32((0xf7032000 + 0x370), 0x01); + mmio_write_32((0xf7032000 + 0x360), 0x60); + mmio_write_32((0xf7032000 + 0x364), 0x60); + + mmio_write_32((0xf7032000 + 0x114), 0x1000); + + data = mmio_read_32((0xf7032000 + 0x110)); + data |= (3 << 12); + mmio_write_32((0xf7032000 + 0x110), data); + + data = mmio_read_32((0xf7032000 + 0x110)); + data |= (1 << 4); + mmio_write_32((0xf7032000 + 0x110), data); + + + data = mmio_read_32((0xf7032000 + 0x110)); + data &= ~0x7; + data |= 0x5; + mmio_write_32((0xf7032000 + 0x110), data); + dsb(); + mdelay(10); + + + do { + data = mmio_read_32((0xf6504000 + 0x008)); + data &= (3 << 20); + } while (data != (3 << 20)); + dsb(); + mdelay(10); + + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~((1 << 0) | (1 << 11)); + mmio_write_32((0xf6504000 + 0x054), data); + mdelay(10); + + data = mmio_read_32((0xf7032000 + 0x104)); + data &= ~(3 << 8); + data |= (1 << 8); + mmio_write_32((0xf7032000 + 0x104), data); + + data = mmio_read_32((0xf7032000 + 0x100)); + data |= (1 << 0); + mmio_write_32((0xf7032000 + 0x100), data); + dsb(); + + do { + data = mmio_read_32((0xf7032000 + 0x100)); + data &= (1 << 2); + } while (data != (1 << 2)); + + data = mmio_read_32((0xf6504000 + 0x06c)); + data &= ~0xffff; + data |= 0x56; + mmio_write_32((0xf6504000 + 0x06c), data); + + data = mmio_read_32((0xf6504000 + 0x06c)); + data &= ~(0xffffffu << 8); + data |= 0xc7a << 8; + mmio_write_32((0xf6504000 + 0x06c), data); + + data = mmio_read_32((0xf6504000 + 0x058)); + data &= ((1 << 13) - 1); + data |= 0xccb; + mmio_write_32((0xf6504000 + 0x058), data); + + mmio_write_32((0xf6504000 + 0x060), 0x1fff); + mmio_write_32((0xf6504000 + 0x064), 0x1ffffff); + mmio_write_32((0xf6504000 + 0x068), 0x7fffffff); + mmio_write_32((0xf6504000 + 0x05c), 0x1); + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~(0xf << 12); + data |= 1 << 12; + mmio_write_32((0xf6504000 + 0x054), data); + dsb(); + + + data = mmio_read_32((0xf7032000 + 0x000)); + data &= ~(1 << 0); + mmio_write_32((0xf7032000 + 0x000), data); + + mmio_write_32((0xf7032000 + 0x004), 0x5110207d); + mmio_write_32((0xf7032000 + 0x134), 0x10000005); + data = mmio_read_32((0xf7032000 + 0x134)); + + + data = mmio_read_32((0xf7032000 + 0x000)); + data |= (1 << 0); + mmio_write_32((0xf7032000 + 0x000), data); + + mmio_write_32((0xf7032000 + 0x368), 0x100da); + data = mmio_read_32((0xf7032000 + 0x378)); + data &= ~((1 << 7) - 1); + data |= 0x6b; + mmio_write_32((0xf7032000 + 0x378), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x378)); + tmp = data & 0x7f; + data = (data & (0x7f << 8)) >> 8; + if (data != tmp) + continue; + data = mmio_read_32((0xf7032000 + 0x37c)); + } while (!(data & 1)); + + data = mmio_read_32((0xf7032000 + 0x104)); + data &= ~((3 << 0) | + (3 << 8)); + cpuext_cfg = 1; + ddr_cfg = 1; + data |= cpuext_cfg | (ddr_cfg << 8); + mmio_write_32((0xf7032000 + 0x104), data); + dsb(); + + do { + data = mmio_read_32((0xf7032000 + 0x104)); + tmp = (data & (3 << 16)) >> 16; + if (cpuext_cfg != tmp) + continue; + tmp = (data & (3 << 24)) >> 24; + if (ddr_cfg != tmp) + continue; + data = mmio_read_32((0xf7032000 + 0x000)); + data &= 1 << 28; + } while (!data); + + data = mmio_read_32((0xf7032000 + 0x100)); + data &= ~(1 << 0); + mmio_write_32((0xf7032000 + 0x100), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x100)); + data &= (1 << 1); + } while (data != (1 << 1)); + mdelay(1000); + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~(1 << 28); + mmio_write_32((0xf6504000 + 0x054), data); + dsb(); + + data = mmio_read_32((0xf7032000 + 0x110)); + data &= ~((1 << 4) | + (3 << 12)); + mmio_write_32((0xf7032000 + 0x110), data); +} + +int cat_533mhz_800mhz(void) +{ + unsigned int data, i; + unsigned int bdl[5]; + + + data = mmio_read_32((0xf712c000 + 0x1c8)); + data &= 0xfffff0f0; + data |= 0x100f01; + mmio_write_32((0xf712c000 + 0x1c8), data); + + for (i = 0; i < 0x20; i++) { + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + data = (i << 0x10) + i; + mmio_write_32((0xf712c000 + 0x140), data); + mmio_write_32((0xf712c000 + 0x144), data); + mmio_write_32((0xf712c000 + 0x148), data); + mmio_write_32((0xf712c000 + 0x14c), data); + mmio_write_32((0xf712c000 + 0x150), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x801); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if ((data & 0x400) == 0) { + mdelay(10); + return 0; + } + WARN("lpddr3 cat fail\n"); + data = mmio_read_32((0xf712c000 + 0x1d4)); + if ((data & 0x1f00) && ((data & 0x1f) == 0)) { + bdl[0] = mmio_read_32((0xf712c000 + 0x140)); + bdl[1] = mmio_read_32((0xf712c000 + 0x144)); + bdl[2] = mmio_read_32((0xf712c000 + 0x148)); + bdl[3] = mmio_read_32((0xf712c000 + 0x14c)); + bdl[4] = mmio_read_32((0xf712c000 + 0x150)); + if ((!(bdl[0] & 0x1f001f)) || (!(bdl[1] & 0x1f001f)) || + (!(bdl[2] & 0x1f001f)) || (!(bdl[3] & 0x1f001f)) || + (!(bdl[4] & 0x1f001f))) { + WARN("lpddr3 cat deskew error\n"); + if (i == 0x1f) { + WARN("addrnbdl is max\n"); + return -EINVAL; + } + mmio_write_32((0xf712c000 + 0x008), 0x400); + } else { + WARN("lpddr3 cat other error1\n"); + return -EINVAL; + } + } else { + WARN("lpddr3 cat other error2\n"); + return -EINVAL; + } + } + return -EINVAL; +} + +static void ddrx_rdet(void) +{ + unsigned int data, rdet, bdl[4]; + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= 0xf800ffff; + data |= 0x8f0000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + data = mmio_read_32((0xf712c000 + 0x0dc)); + data &= 0xfffffff0; + data |= 0xf; + mmio_write_32((0xf712c000 + 0x0dc), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x80000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (!(data & 1)); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x100) + WARN("rdet lbs fail\n"); + + bdl[0] = mmio_read_32((0xf712c000 + 0x22c)) & 0x7f; + bdl[1] = mmio_read_32((0xf712c000 + 0x2ac)) & 0x7f; + bdl[2] = mmio_read_32((0xf712c000 + 0x32c)) & 0x7f; + bdl[3] = mmio_read_32((0xf712c000 + 0x3ac)) & 0x7f; + do { + data = mmio_read_32((0xf712c000 + 0x22c)); + data &= ~0x7f; + data |= bdl[0]; + mmio_write_32((0xf712c000 + 0x22c), data); + data = mmio_read_32((0xf712c000 + 0x2ac)); + data &= ~0x7f; + data |= bdl[1]; + mmio_write_32((0xf712c000 + 0x2ac), data); + data = mmio_read_32((0xf712c000 + 0x32c)); + data &= ~0x7f; + data |= bdl[2]; + mmio_write_32((0xf712c000 + 0x32c), data); + data = mmio_read_32((0xf712c000 + 0x3ac)); + data &= ~0x7f; + data |= bdl[3]; + mmio_write_32((0xf712c000 + 0x3ac), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + rdet = data & 0x100; + if (rdet) { + INFO("rdet ds fail\n"); + mmio_write_32((0xf712c000 + 0x008), 0x100); + } + bdl[0]++; + bdl[1]++; + bdl[2]++; + bdl[3]++; + } while (rdet); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x30000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x100) + INFO("rdet rbs av fail\n"); +} + +static void ddrx_wdet(void) +{ + unsigned int data, wdet, zero_bdl = 0, dq[4]; + int i; + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf; + data |= 0xf; + mmio_write_32((0xf712c000 + 0x0d0), data); + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= ~0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x8000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x200) + INFO("wdet lbs fail\n"); + + dq[0] = mmio_read_32((0xf712c000 + 0x234)) & 0x1f00; + dq[1] = mmio_read_32((0xf712c000 + 0x2b4)) & 0x1f00; + dq[2] = mmio_read_32((0xf712c000 + 0x334)) & 0x1f00; + dq[3] = mmio_read_32((0xf712c000 + 0x3b4)) & 0x1f00; + + do { + mmio_write_32((0xf712c000 + 0x234), dq[0]); + mmio_write_32((0xf712c000 + 0x2b4), dq[1]); + mmio_write_32((0xf712c000 + 0x334), dq[2]); + mmio_write_32((0xf712c000 + 0x3b4), dq[3]); + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= ~0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x4000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + wdet = data & 0x200; + if (wdet) { + INFO("wdet ds fail\n"); + mmio_write_32((0xf712c000 + 0x008), 0x200); + } + mdelay(10); + + for (i = 0; i < 4; i++) { + data = mmio_read_32((0xf712c000 + 0x210 + i * 0x80)); + if ((!(data & 0x1f)) || (!(data & 0x1f00)) || + (!(data & 0x1f0000)) || (!(data & 0x1f000000))) + zero_bdl = 1; + data = mmio_read_32((0xf712c000 + 0x214 + i * 0x80)); + if ((!(data & 0x1f)) || (!(data & 0x1f00)) || + (!(data & 0x1f0000)) || (!(data & 0x1f000000))) + zero_bdl = 1; + data = mmio_read_32((0xf712c000 + 0x218 + i * 0x80)); + if (!(data & 0x1f)) + zero_bdl = 1; + if (zero_bdl) { + if (i == 0) + dq[0] = dq[0] - 0x100; + if (i == 1) + dq[1] = dq[1] - 0x100; + if (i == 2) + dq[2] = dq[2] - 0x100; + if (i == 3) + dq[3] = dq[3] - 0x100; + } + } + } while (wdet); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x3000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x200) + INFO("wdet rbs av fail\n"); +} + +void set_ddrc_150mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x1); + mmio_write_32((0xf7032000 + 0x5a8), 0x7); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x31); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f); + mmio_write_32((0xf712c000 + 0x00c), 0xf0f); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x7200000); + mmio_write_32((0xf712c000 + 0x258), 0x720); + mmio_write_32((0xf712c000 + 0x2d8), 0x720); + mmio_write_32((0xf712c000 + 0x358), 0x720); + mmio_write_32((0xf712c000 + 0x3d8), 0x720); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x30c82355); + mmio_write_32((0xf712c000 + 0x034), 0x62112bb); + mmio_write_32((0xf712c000 + 0x038), 0x20041022); + mmio_write_32((0xf712c000 + 0x03c), 0x63177497); + mmio_write_32((0xf712c000 + 0x040), 0x3008407); + mmio_write_32((0xf712c000 + 0x064), 0x10483); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x184; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data &= 0xbfffffff; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0x90420880); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x146d); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb3290d08); + mmio_write_32((0xf7128000 + 0x104), 0x9621821); + mmio_write_32((0xf7128000 + 0x108), 0x45009023); + mmio_write_32((0xf7128000 + 0x10c), 0xaf44c145); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x11080806); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 8) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x8) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 150mhz\n"); +} + +void set_ddrc_266mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x3); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x31); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f); + mmio_write_32((0xf712c000 + 0x00c), 0xf0f); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x7200000); + mmio_write_32((0xf712c000 + 0x258), 0x720); + mmio_write_32((0xf712c000 + 0x2d8), 0x720); + mmio_write_32((0xf712c000 + 0x358), 0x720); + mmio_write_32((0xf712c000 + 0x3d8), 0x720); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x510d4455); + mmio_write_32((0xf712c000 + 0x034), 0x8391ebb); + mmio_write_32((0xf712c000 + 0x038), 0x2005103c); + mmio_write_32((0xf712c000 + 0x03c), 0x6329950b); + mmio_write_32((0xf712c000 + 0x040), 0x300858c); + mmio_write_32((0xf712c000 + 0x064), 0x10483); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x184; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data &= 0xbfffffff; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0x90420880); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x146d); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb441d50d); + mmio_write_32((0xf7128000 + 0x104), 0xf721839); + mmio_write_32((0xf7128000 + 0x108), 0x5500f03f); + mmio_write_32((0xf7128000 + 0x10c), 0xaf486145); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x12080d06); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 8) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x8) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 266mhz\n"); +} + +void set_ddrc_400mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x2); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x31); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f); + mmio_write_32((0xf712c000 + 0x00c), 0xf0f); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x7200000); + mmio_write_32((0xf712c000 + 0x258), 0x720); + mmio_write_32((0xf712c000 + 0x2d8), 0x720); + mmio_write_32((0xf712c000 + 0x358), 0x720); + mmio_write_32((0xf712c000 + 0x3d8), 0x720); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x75525655); + mmio_write_32((0xf712c000 + 0x034), 0xa552abb); + mmio_write_32((0xf712c000 + 0x038), 0x20071059); + mmio_write_32((0xf712c000 + 0x03c), 0x633e8591); + mmio_write_32((0xf712c000 + 0x040), 0x3008691); + mmio_write_32((0xf712c000 + 0x064), 0x10483); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x184; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data &= 0xbfffffff; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0x90420880); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x146d); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb55a9d12); + mmio_write_32((0xf7128000 + 0x104), 0x17721855); + mmio_write_32((0xf7128000 + 0x108), 0x7501505f); + mmio_write_32((0xf7128000 + 0x10c), 0xaf4ca245); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x13081306); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 8) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x8) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 400mhz\n"); +} + +void set_ddrc_533mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x3); + mmio_write_32((0xf7032000 + 0x5a8), 0x11111); + data = mmio_read_32((0xf7032000 + 0x104)); + data |= 0x100; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x30); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x6400000); + mmio_write_32((0xf712c000 + 0x258), 0x640); + mmio_write_32((0xf712c000 + 0x2d8), 0x640); + mmio_write_32((0xf712c000 + 0x358), 0x640); + mmio_write_32((0xf712c000 + 0x3d8), 0x640); + mmio_write_32((0xf712c000 + 0x018), 0x0); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x9dd87855); + mmio_write_32((0xf712c000 + 0x034), 0xa7138bb); + mmio_write_32((0xf712c000 + 0x038), 0x20091477); + mmio_write_32((0xf712c000 + 0x03c), 0x84534e16); + mmio_write_32((0xf712c000 + 0x040), 0x3008817); + mmio_write_32((0xf712c000 + 0x064), 0x106c3); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x305; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0xd0420900); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x140f); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("failed to init lpddr3 rank0 dram phy\n"); + return; + } + cat_533mhz_800mhz(); + + mmio_write_32((0xf712c000 + 0x004), 0xf1); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb77b6718); + mmio_write_32((0xf7128000 + 0x104), 0x1e82a071); + mmio_write_32((0xf7128000 + 0x108), 0x9501c07e); + mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x13181908); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + ddrx_rdet(); + ddrx_wdet(); + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 533mhz\n"); +} + +void set_ddrc_800mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x2); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x30); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x5400000); + mmio_write_32((0xf712c000 + 0x258), 0x540); + mmio_write_32((0xf712c000 + 0x2d8), 0x540); + mmio_write_32((0xf712c000 + 0x358), 0x540); + mmio_write_32((0xf712c000 + 0x3d8), 0x540); + mmio_write_32((0xf712c000 + 0x018), 0x0); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0xe663ab77); + mmio_write_32((0xf712c000 + 0x034), 0xea952db); + mmio_write_32((0xf712c000 + 0x038), 0x200d1cb1); + mmio_write_32((0xf712c000 + 0x03c), 0xc67d0721); + mmio_write_32((0xf712c000 + 0x040), 0x3008aa1); + mmio_write_32((0xf712c000 + 0x064), 0x11a43); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x507; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xffffffef; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= 0xffffdfff; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0xd0420900); + + mmio_write_32((0xf7128000 + 0x040), 0x2001); + mmio_write_32((0xf712c000 + 0x004), 0x140f); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + WARN("failed to init lpddr3 rank0 dram phy\n"); + return; + } + cat_533mhz_800mhz(); + + mmio_write_32((0xf712c000 + 0x004), 0xf1); + mmio_write_32((0xf7128000 + 0x050), 0x100023); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0x755a9d12); + mmio_write_32((0xf7128000 + 0x104), 0x1753b055); + mmio_write_32((0xf7128000 + 0x108), 0x7401505f); + mmio_write_32((0xf7128000 + 0x10c), 0x578ca244); + mmio_write_32((0xf7128000 + 0x110), 0x10700000); + mmio_write_32((0xf7128000 + 0x114), 0x13141306); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + ddrx_rdet(); + ddrx_wdet(); + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 800mhz\n"); +} + +static void ddrc_common_init(int freq) +{ + unsigned int data; + + mmio_write_32((0xf7120000 + 0x020), 0x1); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32((0xf7121400 + 0x104), 0xf); + mmio_write_32((0xf7121800 + 0x104), 0xf); + mmio_write_32((0xf7121c00 + 0x104), 0xf); + mmio_write_32((0xf7122000 + 0x104), 0xf); + mmio_write_32((0xf7128000 + 0x02c), 0x6); + mmio_write_32((0xf7128000 + 0x020), 0x30003); + mmio_write_32((0xf7128000 + 0x028), 0x310201); + mmio_write_32((0xf712c000 + 0x1e4), 0xfe007600); + mmio_write_32((0xf7128000 + 0x01c), 0xaf001); + + + data = mmio_read_32((0xf7128000 + 0x280)); + data |= 1 << 7; + mmio_write_32((0xf7128000 + 0x280), data); + mmio_write_32((0xf7128000 + 0x244), 0x3); + + if (freq == DDR_FREQ_800M) + mmio_write_32((0xf7128000 + 0x240), 167 * (freq / 2) / 1024); + else + mmio_write_32((0xf7128000 + 0x240), 167 * freq / 1024); + + data = mmio_read_32((0xf712c000 + 0x080)); + data &= 0xffff; + data |= 0x4002000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf7128000 + 0x000), 0x0); + do { + data = mmio_read_32((0xf7128000 + 0x294)); + } while (data & 1); + mmio_write_32((0xf7128000 + 0x000), 0x2); +} + + +static int dienum_det_and_rowcol_cfg(void) +{ + unsigned int data; + + mmio_write_32((0xf7128000 + 0x210), 0x87); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)) & 0xfc; + switch (data) { + case 0x18: + mmio_write_32((0xf7128000 + 0x060), 0x132); + mmio_write_32((0xf7128000 + 0x064), 0x132); + mmio_write_32((0xf7120000 + 0x100), 0x1600); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x40000000); + break; + case 0x1c: + mmio_write_32((0xf7128000 + 0x060), 0x142); + mmio_write_32((0xf7128000 + 0x064), 0x142); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000); + break; + case 0x58: + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000); + break; + default: + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000); + break; + } + if (!data) + return -EINVAL; + return 0; +} + +static int detect_ddr_chip_info(void) +{ + unsigned int data, mr5, mr6, mr7; + + mmio_write_32((0xf7128000 + 0x210), 0x57); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr5 = data & 0xff; + switch (mr5) { + case 1: + INFO("Samsung DDR\n"); + break; + case 6: + INFO("Hynix DDR\n"); + break; + case 3: + INFO("Elpida DDR\n"); + break; + default: + INFO("DDR from other vendors\n"); + break; + } + + mmio_write_32((0xf7128000 + 0x210), 0x67); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr6 = data & 0xff; + mmio_write_32((0xf7128000 + 0x210), 0x77); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr7 = data & 0xff; + data = mr5 + (mr6 << 8) + (mr7 << 16); + return data; +} + +void ddr_phy_reset(void) +{ + mmio_write_32(0xf7030340, 0xa000); + mmio_write_32(0xf7030344, 0xa000); +} + +void lpddrx_save_ddl_para_bypass(uint32_t *ddr_ddl_para, unsigned int index) +{ + uint32_t value; + uint32_t cnt = index; + uint32_t i; + + for (i = 0; i < 4; i++) { + value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80); + ddr_ddl_para[cnt++] = value; + } +} + +void lpddrx_save_ddl_para_mission(uint32_t *ddr_ddl_para, unsigned int index) +{ + uint32_t value; + uint32_t cnt = index; + uint32_t i; + + value = mmio_read_32(0xf712c000 + 0x140); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x144); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x148); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x14c); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x150); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x1d4); + ddr_ddl_para[cnt++] = value; + for (i = 0; i < 4; i++) { + value = mmio_read_32(0xf712c000 + 0x210 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x214 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x218 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x21c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x220 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x224 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x228 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x230 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x234 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x238 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80); + ddr_ddl_para[cnt++] = value; + } + value = mmio_read_32(0xf712c000 + 0x168); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x24c + 0 * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x24c + 2 * 0x80); + ddr_ddl_para[cnt++] = value; +} + +int lpddr3_freq_init(int freq) +{ + set_ddrc_150mhz(); + lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, 0); + if (freq > DDR_FREQ_150M) { + ddr_phy_reset(); + set_ddrc_266mhz(); + lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16); + } + if (freq > DDR_FREQ_266M) { + ddr_phy_reset(); + set_ddrc_400mhz(); + lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16 * 2); + } + if (freq > DDR_FREQ_400M) { + ddr_phy_reset(); + set_ddrc_533mhz(); + lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16 * 3); + } + if (freq > DDR_FREQ_533M) { + ddr_phy_reset(); + set_ddrc_800mhz(); + lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16 * 3 + 61); + } + return 0; +} + +static void init_ddr(int freq) +{ + unsigned int data; + int ret; + + + data = mmio_read_32((0xf7032000 + 0x030)); + data |= 1; + mmio_write_32((0xf7032000 + 0x030), data); + data = mmio_read_32((0xf7032000 + 0x010)); + data |= 1; + mmio_write_32((0xf7032000 + 0x010), data); + + udelay(300); + do { + data = mmio_read_32((0xf7032000 + 0x030)); + data &= 3 << 28; + } while (data != (3 << 28)); + do { + data = mmio_read_32((0xf7032000 + 0x010)); + data &= 3 << 28; + } while (data != (3 << 28)); + + ret = lpddr3_freq_init(freq); + if (ret) + return; +} + +static void init_ddrc_qos(void) +{ + unsigned int port, data; + + mmio_write_32((0xf7124000 + 0x088), 1); + + port = 0; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x11111111); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x11111111); + mmio_write_32((0xf7120000 + 0x400 + 0 * 0x10), 0x001d0007); + + for (port = 3; port <= 4; port++) { + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x77777777); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x77777777); + } + + port = 1; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567); + + mmio_write_32((0xf7124000 + 0x1f0), 0); + mmio_write_32((0xf7124000 + 0x0bc), 0x3020100); + mmio_write_32((0xf7124000 + 0x0d0), 0x3020100); + mmio_write_32((0xf7124000 + 0x1f4), 0x01000100); + mmio_write_32((0xf7124000 + 0x08c + 0 * 4), 0xd0670402); + mmio_write_32((0xf7124000 + 0x068 + 0 * 4), 0x31); + mmio_write_32((0xf7124000 + 0x000), 0x7); + + data = mmio_read_32((0xf7124000 + 0x09c)); + data &= ~0xff0000; + data |= 0x400000; + mmio_write_32((0xf7124000 + 0x09c), data); + data = mmio_read_32((0xf7124000 + 0x0ac)); + data &= ~0xff0000; + data |= 0x400000; + mmio_write_32((0xf7124000 + 0x0ac), data); + port = 2; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567); + + + mmio_write_32((0xf7124000 + 0x09c), 0xff7fff); + mmio_write_32((0xf7124000 + 0x0a0), 0xff); + mmio_write_32((0xf7124000 + 0x0ac), 0xff7fff); + mmio_write_32((0xf7124000 + 0x0b0), 0xff); + mmio_write_32((0xf7124000 + 0x0bc), 0x3020100); + mmio_write_32((0xf7124000 + 0x0d0), 0x3020100); +} + +void hikey_ddr_init(unsigned int ddr_freq) +{ + uint32_t data; + + assert((ddr_freq == DDR_FREQ_150M) || (ddr_freq == DDR_FREQ_266M) || + (ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_533M) || + (ddr_freq == DDR_FREQ_800M)); + init_pll(); + init_freq(); + + init_ddr(ddr_freq); + + ddrc_common_init(ddr_freq); + dienum_det_and_rowcol_cfg(); + detect_ddr_chip_info(); + + if ((ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_800M)) { + data = mmio_read_32(0xf7032000 + 0x010); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x010, data); + } else if ((ddr_freq == DDR_FREQ_266M) || (ddr_freq == DDR_FREQ_533M)) { + data = mmio_read_32(0xf7032000 + 0x030); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x030, data); + } else { + data = mmio_read_32(0xf7032000 + 0x010); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x010, data); + data = mmio_read_32(0xf7032000 + 0x030); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x030, data); + } + dsb(); + isb(); + + /* + * Test memory access. Do not use address 0x0 because the compiler + * may assume it is not a valid address and generate incorrect code + * (GCC 4.9.1 without -fno-delete-null-pointer-checks for instance). + */ + mmio_write_32(0x4, 0xa5a55a5a); + INFO("ddr test value:0x%x\n", mmio_read_32(0x4)); + init_ddrc_qos(); +} diff --git a/plat/hisilicon/hikey/hikey_image_load.c b/plat/hisilicon/hikey/hikey_image_load.c new file mode 100644 index 0000000..0ab1ca4 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/plat/hisilicon/hikey/hikey_io_storage.c b/plat/hisilicon/hikey/hikey_io_storage.c new file mode 100644 index 0000000..fd610d8 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_io_storage.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/io/io_block.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_fip.h> +#include <drivers/io/io_memmap.h> +#include <drivers/io/io_storage.h> +#include <drivers/mmc.h> +#include <drivers/partition/partition.h> +#include <lib/mmio.h> +#include <lib/semihosting.h> +#include <tools_share/firmware_image_package.h> + +#include "hikey_private.h" + +#define EMMC_BLOCK_SHIFT 9 + +/* Page 1024, since only a few pages before 2048 are used as partition table */ +#define SERIALNO_EMMC_OFFSET (1024 * 512) + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const io_dev_connector_t *emmc_dev_con; +static uintptr_t emmc_dev_handle; +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; + +static int check_emmc(const uintptr_t spec); +static int check_fip(const uintptr_t spec); + +static io_block_spec_t emmc_fip_spec; + +static const io_block_spec_t emmc_gpt_spec = { + .offset = 0, + .length = PLAT_PARTITION_BLOCK_SIZE * + (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), +}; + +static const io_block_dev_spec_t emmc_dev_spec = { + /* It's used as temp buffer in block driver. */ +#ifdef IMAGE_BL1 + .buffer = { + .offset = HIKEY_BL1_MMC_DATA_BASE, + .length = HIKEY_BL1_MMC_DATA_SIZE, + }, +#else + .buffer = { + .offset = HIKEY_MMC_DATA_BASE, + .length = HIKEY_MMC_DATA_SIZE, + }, +#endif + .ops = { + .read = mmc_read_blocks, + .write = mmc_write_blocks, + }, + .block_size = MMC_BLOCK_SIZE, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_fip_spec, + check_emmc + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_bl2_uuid_spec, + check_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + check_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + check_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + check_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + check_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + check_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_key_cert_uuid_spec, + check_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_cert_uuid_spec, + check_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + check_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ + [GPT_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_gpt_spec, + check_emmc + }, +}; + +static int check_emmc(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(emmc_dev_handle, spec, &local_handle); + if (result == 0) + io_close(local_handle); + } + return result; +} + +static int check_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +void hikey_io_setup(void) +{ + int result; + + result = register_io_dev_block(&emmc_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, + &emmc_dev_handle); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); + assert(result == 0); + + /* Ignore improbable errors in release builds */ + (void)result; +} + +int hikey_set_fip_addr(unsigned int image_id, const char *name) +{ + const partition_entry_t *entry; + + if (emmc_fip_spec.length == 0) { + partition_init(GPT_IMAGE_ID); + entry = get_partition_entry(name); + if (entry == NULL) { + ERROR("Could NOT find the %s partition!\n", name); + return -ENOENT; + } + emmc_fip_spec.offset = entry->start; + emmc_fip_spec.length = entry->length; + } + return 0; +} + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} diff --git a/plat/hisilicon/hikey/hikey_pm.c b/plat/hisilicon/hikey/hikey_pm.c new file mode 100644 index 0000000..05c1e7f --- /dev/null +++ b/plat/hisilicon/hikey/hikey_pm.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/sp804_delay_timer.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> + +#include <hi6220.h> +#include <hikey_def.h> +#include <hisi_ipc.h> +#include <hisi_pwrc.h> +#include <hisi_sram_map.h> + +#define CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +static uintptr_t hikey_sec_entrypoint; + +static int hikey_pwr_domain_on(u_register_t mpidr) +{ + int cpu, cluster; + int curr_cluster; + + cluster = MPIDR_AFFLVL1_VAL(mpidr); + cpu = MPIDR_AFFLVL0_VAL(mpidr); + curr_cluster = MPIDR_AFFLVL1_VAL(read_mpidr()); + if (cluster != curr_cluster) + hisi_ipc_cluster_on(cpu, cluster); + + hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint); + hisi_pwrc_enable_debug(cpu, cluster); + hisi_ipc_cpu_on(cpu, cluster); + + return 0; +} + +static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + int cpu, cluster; + + mpidr = read_mpidr(); + cluster = MPIDR_AFFLVL1_VAL(mpidr); + cpu = MPIDR_AFFLVL0_VAL(mpidr); + + + /* + * Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + /* Zero the jump address in the mailbox for this cpu */ + hisi_pwrc_set_core_bx_addr(cpu, cluster, 0); + + /* Program the GIC per-cpu distributor or re-distributor interface */ + gicv2_pcpu_distif_init(); + /* Enable the GIC cpu interface */ + gicv2_cpuif_enable(); +} + +void hikey_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + int cpu, cluster; + + mpidr = read_mpidr(); + cluster = MPIDR_AFFLVL1_VAL(mpidr); + cpu = MPIDR_AFFLVL0_VAL(mpidr); + + gicv2_cpuif_disable(); + hisi_ipc_cpu_off(cpu, cluster); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_cluster_off(cpu, cluster); + } +} + +static void hikey_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cpu = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + + /* Program the jump address for the target cpu */ + hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint); + + gicv2_cpuif_disable(); + + if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + hisi_ipc_cpu_suspend(cpu, cluster); + } + + /* Perform the common cluster specific operations */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_pwrc_set_cluster_wfi(1); + hisi_pwrc_set_cluster_wfi(0); + hisi_ipc_psci_system_off(); + } else + hisi_ipc_cluster_suspend(cpu, cluster); + } +} + +static void hikey_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + unsigned int cluster, cpu; + + /* Nothing to be done on waking up from retention from CPU level */ + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + /* Get the mpidr for this cpu */ + mpidr = read_mpidr_el1(); + cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT; + cpu = mpidr & MPIDR_CPU_MASK; + + /* Enable CCI coherency for cluster */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + hisi_pwrc_set_core_bx_addr(cpu, cluster, 0); + + if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + } else { + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + } +} + +static void hikey_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static void __dead2 hikey_system_off(void) +{ + NOTICE("%s: off system\n", __func__); + + /* Pull down GPIO_0_0 to trigger PMIC shutdown */ + mmio_write_32(0xF8001810, 0x2); /* Pinmux */ + mmio_write_8(0xF8011400, 1); /* Pin direction */ + mmio_write_8(0xF8011004, 0); /* Pin output value */ + + /* Wait for 2s to power off system by PMIC */ + sp804_timer_init(SP804_TIMER0_BASE, 10, 192); + mdelay(2000); + + /* + * PMIC shutdown depends on two conditions: GPIO_0_0 (PWR_HOLD) low, + * and VBUS_DET < 3.6V. For HiKey, VBUS_DET is connected to VDD_4V2 + * through Jumper 1-2. So, to complete shutdown, user needs to manually + * remove Jumper 1-2. + */ + NOTICE("+------------------------------------------+\n"); + NOTICE("| IMPORTANT: Remove Jumper 1-2 to shutdown |\n"); + NOTICE("| DANGER: SoC is still burning. DANGER! |\n"); + NOTICE("| Board will be reboot to avoid overheat |\n"); + NOTICE("+------------------------------------------+\n"); + + /* Send the system reset request */ + mmio_write_32(AO_SC_SYS_STAT0, 0x48698284); + + wfi(); + panic(); +} + +static void __dead2 hikey_system_reset(void) +{ + /* Send the system reset request */ + mmio_write_32(AO_SC_SYS_STAT0, 0x48698284); + isb(); + dsb(); + + wfi(); + panic(); +} + +int hikey_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = + PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + PLAT_MAX_OFF_STATE; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +static int hikey_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static const plat_psci_ops_t hikey_psci_ops = { + .cpu_standby = NULL, + .pwr_domain_on = hikey_pwr_domain_on, + .pwr_domain_on_finish = hikey_pwr_domain_on_finish, + .pwr_domain_off = hikey_pwr_domain_off, + .pwr_domain_suspend = hikey_pwr_domain_suspend, + .pwr_domain_suspend_finish = hikey_pwr_domain_suspend_finish, + .system_off = hikey_system_off, + .system_reset = hikey_system_reset, + .validate_power_state = hikey_validate_power_state, + .validate_ns_entrypoint = hikey_validate_ns_entrypoint, + .get_sys_suspend_power_state = hikey_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + hikey_sec_entrypoint = sec_entrypoint; + + /* + * Initialize PSCI ops struct + */ + *psci_ops = &hikey_psci_ops; + return 0; +} diff --git a/plat/hisilicon/hikey/hikey_private.h b/plat/hisilicon/hikey/hikey_private.h new file mode 100644 index 0000000..b75bc72 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_private.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY_PRIVATE_H +#define HIKEY_PRIVATE_H + +#include <common/bl_common.h> + +#define RANDOM_MAX 0x7fffffffffffffff +#define RANDOM_MAGIC 0x9a4dbeaf + +enum { + DDR_FREQ_150M = 150 * 1000, + DDR_FREQ_266M = 266 * 1000, + DDR_FREQ_400M = 400 * 1000, + DDR_FREQ_533M = 533 * 1000, + DDR_FREQ_800M = 800 * 1000 +}; + +struct random_serial_num { + uint64_t magic; + uint64_t data; + char serialno[32]; +}; + +/* + * Function and variable prototypes + */ +void hikey_init_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void hikey_init_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void hikey_ddr_init(unsigned int ddr_freq); +void hikey_io_setup(void); + +void hikey_sp804_init(void); +void hikey_gpio_init(void); +void hikey_pmussi_init(void); +void hikey_hi6553_init(void); +void init_mmc0_pll(void); +void reset_mmc0_clk(void); +void init_media_clk(void); +void init_mmc1_pll(void); +void reset_mmc1_clk(void); +void hikey_mmc_pll_init(void); +void hikey_rtc_init(void); + +int hikey_get_partition_size(const char *arg, int left, char *response); +int hikey_get_partition_type(const char *arg, int left, char *response); + +int hikey_erase(const char *arg); +int hikey_flash(const char *arg); +int hikey_oem(const char *arg); +int hikey_reboot(const char *arg); +void hikey_security_setup(void); + +const char *hikey_init_serialno(void); +int hikey_read_serialno(struct random_serial_num *serialno); +int hikey_write_serialno(struct random_serial_num *serialno); + +void init_acpu_dvfs(void); + +int hikey_set_fip_addr(unsigned int image_id, const char *name); + +#endif /* HIKEY_PRIVATE_H */ diff --git a/plat/hisilicon/hikey/hikey_rotpk.S b/plat/hisilicon/hikey/hikey_rotpk.S new file mode 100644 index 0000000..f308eee --- /dev/null +++ b/plat/hisilicon/hikey/hikey_rotpk.S @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global hikey_rotpk_hash + .global hikey_rotpk_hash_end + .section .rodata.hikey_rotpk_hash, "a" +hikey_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +hikey_rotpk_hash_end: diff --git a/plat/hisilicon/hikey/hikey_security.c b/plat/hisilicon/hikey/hikey_security.c new file mode 100644 index 0000000..4b95939 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_security.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#include <platform_def.h> + +#include <common/debug.h> +#include <lib/utils_def.h> + +#include "hikey_private.h" + +#define PORTNUM_MAX 5 + +#define MDDRC_SECURITY_BASE 0xF7121000 + +struct int_en_reg { + unsigned in_en:1; + unsigned reserved:31; +}; + +struct rgn_map_reg { + unsigned rgn_base_addr:24; + unsigned rgn_size:6; + unsigned reserved:1; + unsigned rgn_en:1; +}; + +struct rgn_attr_reg { + unsigned sp:4; + unsigned security_inv:1; + unsigned reserved_0:3; + unsigned mid_en:1; + unsigned mid_inv:1; + unsigned reserved_1:6; + unsigned rgn_en:1; + unsigned subrgn_disable:16; +}; + +static volatile struct int_en_reg *get_int_en_reg(uint32_t base) +{ + uint64_t addr = base + 0x20; + return (struct int_en_reg *)addr; +} + +static volatile struct rgn_map_reg *get_rgn_map_reg(uint32_t base, int region, int port) +{ + uint64_t addr = base + 0x100 + 0x10 * region + 0x400 * (uint64_t)port; + return (struct rgn_map_reg *)addr; +} + +static volatile struct rgn_attr_reg *get_rgn_attr_reg(uint32_t base, int region, + int port) +{ + uint64_t addr = base + 0x104 + 0x10 * region + 0x400 * (uint64_t)port; + return (struct rgn_attr_reg *)addr; +} + +/* + * Configure secure memory region + * region_size must be a power of 2 and at least 64KB + * region_base must be region_size aligned + */ +static void sec_protect(uint32_t region_base, uint32_t region_size, + int region) +{ + volatile struct int_en_reg *int_en; + volatile struct rgn_map_reg *rgn_map; + volatile struct rgn_attr_reg *rgn_attr; + uint32_t i = 0; + + /* ensure secure region number is between 1-15 */ + assert(region > 0 && region < 16); + /* ensure secure region size is a power of 2 >= 64KB */ + assert(IS_POWER_OF_TWO(region_size) && region_size >= 0x10000); + /* ensure secure region address is aligned to region size */ + assert(!(region_base & (region_size - 1))); + + INFO("BL2: TrustZone: protecting %u bytes of memory at 0x%x\n", region_size, + region_base); + + int_en = get_int_en_reg(MDDRC_SECURITY_BASE); + int_en->in_en = 0x1; + + for (i = 0; i < PORTNUM_MAX; i++) { + rgn_map = get_rgn_map_reg(MDDRC_SECURITY_BASE, region, i); + rgn_attr = get_rgn_attr_reg(MDDRC_SECURITY_BASE, region, i); + rgn_map->rgn_base_addr = region_base >> 16; + rgn_attr->subrgn_disable = 0x0; + rgn_attr->sp = (i == 3) ? 0xC : 0x0; + rgn_map->rgn_size = __builtin_ffs(region_size) - 2; + rgn_map->rgn_en = 0x1; + } +} + +/******************************************************************************* + * Initialize the secure environment. + ******************************************************************************/ +void hikey_security_setup(void) +{ + sec_protect(DDR_SEC_BASE, DDR_SEC_SIZE, 1); + sec_protect(DDR_SDP_BASE, DDR_SDP_SIZE, 2); +} diff --git a/plat/hisilicon/hikey/hikey_tbbr.c b/plat/hisilicon/hikey/hikey_tbbr.c new file mode 100644 index 0000000..b7dda8d --- /dev/null +++ b/plat/hisilicon/hikey/hikey_tbbr.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> + +extern char hikey_rotpk_hash[], hikey_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = hikey_rotpk_hash; + *key_len = hikey_rotpk_hash_end - hikey_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/plat/hisilicon/hikey/hikey_topology.c b/plat/hisilicon/hikey/hikey_topology.c new file mode 100644 index 0000000..7890eb7 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_topology.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <arch.h> +#include <lib/psci/psci.h> + +/* + * The HiKey power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char hikey_power_domain_tree_desc[] = { + /* Number of root nodes */ + 1, + /* Number of clusters */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, + /* Number of children for the second cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the HiKey topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hikey_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/plat/hisilicon/hikey/hisi_dvfs.c b/plat/hisilicon/hikey/hisi_dvfs.c new file mode 100644 index 0000000..22a67fd --- /dev/null +++ b/plat/hisilicon/hikey/hisi_dvfs.c @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/console.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <hi6220.h> +#include <hi6553.h> +#include <hisi_sram_map.h> + +#define ACPU_FREQ_MAX_NUM 5 +#define ACPU_OPP_NUM 7 + +#define ACPU_VALID_VOLTAGE_MAGIC (0x5A5AC5C5) + +#define ACPU_WAIT_TIMEOUT (200) +#define ACPU_WAIT_FOR_WFI_TIMOUT (2000) +#define ACPU_DFS_STATE_CNT (0x10000) + +struct acpu_dvfs_sram_stru { + unsigned int magic; + unsigned int support_freq_num; + unsigned int support_freq_max; + unsigned int start_prof; + unsigned int vol[ACPU_OPP_NUM]; +}; + +struct acpu_volt_cal_para { + unsigned int freq; + unsigned int ul_vol; + unsigned int dl_vol; + unsigned int core_ref_hpm; +}; + +struct ddr_volt_cal_para { + unsigned int freq; + unsigned int ul_vol; + unsigned int dl_vol; + unsigned int ddr_ref_hpm; +}; + +struct acpu_dvfs_opp_para { + unsigned int freq; + unsigned int acpu_clk_profile0; + unsigned int acpu_clk_profile1; + unsigned int acpu_vol_profile; + unsigned int acpu_pll_freq; + unsigned int acpu_pll_frac; +}; + +unsigned int efuse_acpu_freq[] = { + 1200000, 1250000, 1300000, 1350000, + 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, + 1800000, 1850000, 1900000, 1950000, +}; + +struct acpu_dvfs_opp_para hi6220_acpu_profile[] = { + { 208000, 0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 }, + { 432000, 0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 }, + { 729000, 0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 }, + { 960000, 0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 }, + { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 }, + { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, + { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, +}; + +struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile; +struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf = + (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; + +static inline void write_reg_mask(uintptr_t addr, + uint32_t val, uint32_t mask) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg = (reg & ~(mask)) | val; + mmio_write_32(addr, reg); +} + +static inline uint32_t read_reg_mask(uintptr_t addr, + uint32_t mask, uint32_t offset) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg &= (mask << offset); + return (reg >> offset); +} + +static int acpu_dvfs_syspll_cfg(unsigned int prof_id) +{ + uint32_t reg0 = 0; + uint32_t count = 0; + uint32_t clk_div_status = 0; + + /* + * step 1: + * - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; + */ + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12); + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4, 0x1 << 4); + + /* + * step 2: + * - ACPUSYSPLLCFG.acpu_syspll_div_cfg: + * 208MHz, set to 0x5; + * 500MHz, set to 0x2; + * other opps set to 0x1 + */ + if (prof_id == 0) + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0); + else if (prof_id == 1) + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0); + else + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0); + + /* + * step 3: + * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0 + * - ACPU_SC_VD_CTRL.tune_en_int = 0 + * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1 + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 + */ + clk_div_status = 0x3; + do { + reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: clk div status timeout!\n", __func__); + return -1; + } + } while (clk_div_status != reg0); + + write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11)); + write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8); + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0); + + return 0; +} + +static void acpu_dvfs_clk_div_cfg(unsigned int prof_id, + unsigned int *cpuext_cfg, + unsigned int *acpu_ddr_cfg) +{ + if (prof_id == 0) { + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x1; + } else if (prof_id == 1) { + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x1; + } else { + /* ddr has not been inited */ + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x0; + } +} + +static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof) +{ + unsigned int reg0 = 0; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + unsigned int count = 0; + unsigned int cpuext_cfg_val = 0; + unsigned int acpu_ddr_cfg_val = 0; + int ret = 0; + + /* + * step 1: + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; + * + * step 2: + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz) + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz) + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs) + * + * step 3: + * - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x0; + * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 + */ + ret = acpu_dvfs_syspll_cfg(cur_prof); + if (ret) + return -1; + + /* + * step 4: + * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: syspll sw status timeout\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + /* Enable VD functionality if > 800MHz */ + if (acpu_dvfs_profile[tar_prof].freq > 800000) { + + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); + + /* + * step 5: + * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; + * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; + */ + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); + write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, + ACPU_SC_VD_MASK_PATTERN_VAL, + ACPU_SC_VD_MASK_PATTERN_MASK); + + /* + * step 6: + * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; + * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; + * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; + * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; + */ + mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); + + /* + * step 7: + * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; + * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; + * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; + * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; + * + * step 8: + * - ACPU_SC_VD_CTRL.tune = 0x7; + */ + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); + } + + /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */ + write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */ + mmio_write_32(PMCTRL_ACPUPLLFREQ, + acpu_dvfs_profile[tar_prof].acpu_pll_freq); + mmio_write_32(PMCTRL_ACPUPLLFRAC, + acpu_dvfs_profile[tar_prof].acpu_pll_frac); + + /* + * step 11: + * - wait for 1us; + * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 + */ + count = 0; + while (count < ACPU_WAIT_TIMEOUT) + count++; + + write_reg_mask(PMCTRL_ACPUPLLCTRL, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */ + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); + + /* + * step 13: + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz); + */ + write_reg_mask(PMCTRL_ACPUDESTVOL, + acpu_dvfs_profile[tar_prof].acpu_vol_profile, + ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); + + /* + * step 14: + * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol + * - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1 + * - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg + * - Config ACPUCLKDIV.cpuext_clk_div_cfg; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); + reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); + reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, + SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu destvol cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != reg1) || (reg2 != 0x1)); + + acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); + + /* + * step 15: + * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; + * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; + * - ACPUPLLCTRL.acpupll_timeout = 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); + reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); + reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, + SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu clk div cfg timeout.\n", __func__); + return -1; + } + } while ((reg1 != cpuext_cfg_val) || + (reg0 != acpu_ddr_cfg_val) || + (reg2 != 0x1)); + + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); + + /* + * step 16: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu pll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + if (acpu_dvfs_profile[tar_prof].freq > 800000) + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); + + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, + (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | + (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); + + return 0; +} + +static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof) +{ + unsigned int reg0 = 0; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + unsigned int count = 0; + unsigned int cpuext_cfg_val = 0; + unsigned int acpu_ddr_cfg_val = 0; + int ret = 0; + + ret = acpu_dvfs_syspll_cfg(tar_prof); + if (ret) + return -1; + + /* + * step 4: + * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: syspll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + /* + * Step 5: + * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0 + */ + write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0); + + /* + * step 6 + * - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC + */ + mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq); + mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac); + + /* + * step 7: + * - Wait 1us; + * - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 + */ + count = 0; + while (count < ACPU_WAIT_TIMEOUT) + count++; + + write_reg_mask(PMCTRL_ACPUPLLCTRL, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* Enable VD functionality if > 800MHz */ + if (acpu_dvfs_profile[tar_prof].freq > 800000) { + + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); + + /* + * step 9: + * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; + * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; + */ + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); + write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, + ACPU_SC_VD_MASK_PATTERN_VAL, + ACPU_SC_VD_MASK_PATTERN_MASK); + + /* + * step 10: + * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; + * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; + * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; + * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; + */ + mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); + + /* + * step 11: + * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; + * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; + * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; + * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; + * + * step 12: + * - ACPU_SC_VD_CTRL.tune = 0x7; + */ + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); + } + + /* + * step 13: + * - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, + SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpupll timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); + + /* + * step 14: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpupll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + if (acpu_dvfs_profile[tar_prof].freq > 800000) + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); + + /* + * step 15: + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, + (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | + (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); + + /* + * step 16: + * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, + ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: clk div status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x0); + + acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); + + /* + * step 17: + * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; + * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; + * - PMCTRL_ACPUVOLPMUADDR = 0x1006C; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); + reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu clk div cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != cpuext_cfg_val) || (reg1 != acpu_ddr_cfg_val)); + + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); + + /* + * step 16: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + write_reg_mask(PMCTRL_ACPUDESTVOL, + acpu_dvfs_profile[tar_prof].acpu_vol_profile, + ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); + + /* + * step 19: + * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol + * - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); + reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); + reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, + SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu destvol cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != reg1) || (reg2 != 0x1)); + + return 0; +} + +int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof) +{ + int ret = 0; + + if (curr_prof == target_prof) { + INFO("%s: target_prof is equal curr_prof: is %d!\n", + __func__, curr_prof); + return 0; + } + + if ((curr_prof >= ACPU_FREQ_MAX_NUM) || + (target_prof >= ACPU_FREQ_MAX_NUM)) { + INFO("%s: invalid parameter %d %d\n", + __func__, curr_prof, target_prof); + return -1; + } + + if (target_prof > acpu_dvfs_sram_buf->support_freq_num) + target_prof = acpu_dvfs_sram_buf->support_freq_num; + + if (target_prof < curr_prof) + ret = acpu_dvfs_freq_descend(curr_prof, target_prof); + else if (target_prof > curr_prof) + ret = acpu_dvfs_freq_ascend(curr_prof, target_prof); + + if (ret) { + ERROR("%s: acpu_dvfs_target failed!\n", __func__); + return -1; + } + + /* Complete acpu dvfs setting and set magic number */ + acpu_dvfs_sram_buf->start_prof = target_prof; + acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC; + + mmio_write_32(DDR_DFS_FREQ_ADDR, 800000); + return 0; +} + +static int acpu_dvfs_set_freq(void) +{ + unsigned int i; + unsigned int curr_prof; + unsigned int target_prof; + unsigned int max_freq = 0; + + max_freq = acpu_dvfs_sram_buf->support_freq_max; + + for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) { + + if (max_freq == hi6220_acpu_profile[i].freq) { + target_prof = i; + break; + } + } + + if (i == acpu_dvfs_sram_buf->support_freq_num) { + ERROR("%s: cannot found max freq profile\n", __func__); + return -1; + } + + curr_prof = 0; + target_prof = i; + + /* if max freq is 208MHz, do nothing */ + if (curr_prof == target_prof) + return 0; + + if (acpu_dvfs_target(curr_prof, target_prof)) { + ERROR("%s: set acpu freq failed!", __func__); + return -1; + } + + INFO("%s: support freq num is %d\n", + __func__, acpu_dvfs_sram_buf->support_freq_num); + INFO("%s: start prof is 0x%x\n", + __func__, acpu_dvfs_sram_buf->start_prof); + INFO("%s: magic is 0x%x\n", + __func__, acpu_dvfs_sram_buf->magic); + INFO("%s: voltage:\n", __func__); + for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) + INFO(" - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]); + + NOTICE("%s: set acpu freq success!", __func__); + return 0; +} + +struct acpu_dvfs_volt_setting { + unsigned int magic; + unsigned int support_freq_num; + unsigned int support_freq_max; + unsigned int start_prof; + unsigned int vol[7]; + unsigned int hmp_dly_threshold[7]; +}; + +static void acpu_dvfs_volt_init(void) +{ + struct acpu_dvfs_volt_setting *volt; + + /* + * - set default voltage; + * - set pmu address; + * - set voltage up and down step; + * - set voltage stable time; + */ + mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a); + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda); + mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1); + mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1); + mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60); + mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60); + mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000); + + volt = (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; + volt->magic = 0x5a5ac5c5; + volt->support_freq_num = 5; + volt->support_freq_max = 1200000; + volt->start_prof = 4; + volt->vol[0] = 0x49; + volt->vol[1] = 0x49; + volt->vol[2] = 0x50; + volt->vol[3] = 0x60; + volt->vol[4] = 0x78; + volt->vol[5] = 0x78; + volt->vol[6] = 0x78; + + volt->hmp_dly_threshold[0] = 0x0; + volt->hmp_dly_threshold[1] = 0x0; + volt->hmp_dly_threshold[2] = 0x0; + volt->hmp_dly_threshold[3] = 0x0e8b0e45; + volt->hmp_dly_threshold[4] = 0x10691023; + volt->hmp_dly_threshold[5] = 0x10691023; + volt->hmp_dly_threshold[6] = 0x10691023; + + INFO("%s: success!\n", __func__); +} + +void init_acpu_dvfs(void) +{ + unsigned int i = 0; + + INFO("%s: pmic version %d\n", __func__, + mmio_read_8(HI6553_VERSION_REG)); + + /* init parameters */ + mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]); + INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n", + __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ)); + + /* set maximum support frequency to 1.2GHz */ + for (i = 0; i < ACPU_FREQ_MAX_NUM; i++) + acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile; + + acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM; + acpu_dvfs_sram_buf->support_freq_max = 1200000; + + /* init acpu dvfs */ + acpu_dvfs_volt_init(); + acpu_dvfs_set_freq(); +} diff --git a/plat/hisilicon/hikey/hisi_ipc.c b/plat/hisilicon/hikey/hisi_ipc.c new file mode 100644 index 0000000..43ee0b2 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_ipc.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> + +#include <hisi_ipc.h> +#include <hisi_sram_map.h> + +static int ipc_init; + +static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = { + { + HISI_IPC_MCU_INT_SRC_ACPU0_PD, + HISI_IPC_MCU_INT_SRC_ACPU1_PD, + HISI_IPC_MCU_INT_SRC_ACPU2_PD, + HISI_IPC_MCU_INT_SRC_ACPU3_PD, + }, + { + HISI_IPC_MCU_INT_SRC_ACPU4_PD, + HISI_IPC_MCU_INT_SRC_ACPU5_PD, + HISI_IPC_MCU_INT_SRC_ACPU6_PD, + HISI_IPC_MCU_INT_SRC_ACPU7_PD, + } +}; + +int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu, + unsigned int cluster) +{ + unsigned int val = 0, cpu_val = 0; + int i; + + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + val = val >> (cluster * 16); + + for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) { + + if (cpu == i) + continue; + + cpu_val = (val >> (i * 4)) & 0xF; + if (cpu_val == 0x8) + return 0; + } + + return 1; +} + +int hisi_cpus_powered_off_besides_curr(unsigned int cpu) +{ + unsigned int val; + + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + return (val == (0x8 << (cpu * 4))); +} + +static void hisi_ipc_send(unsigned int ipc_num) +{ + if (!ipc_init) { + printf("error ipc base is null!!!\n"); + return; + } + + mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num); +} + +void hisi_ipc_spin_lock(unsigned int signal) +{ + unsigned int hs_ctrl; + + if (signal >= HISI_IPC_INT_SRC_NUM) + return; + + do { + hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal)); + } while (hs_ctrl); +} + +void hisi_ipc_spin_unlock(unsigned int signal) +{ + if (signal >= HISI_IPC_INT_SRC_NUM) + return; + + mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0); +} + +void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster, + unsigned int mode) +{ + unsigned int val = 0; + unsigned int offset; + + if (mode == HISI_IPC_PM_ON) + offset = cluster * 16 + cpu * 4; + else + offset = cluster * 16 + cpu * 4 + 1; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val); + isb(); + dsb(); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON); +} + +void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF); +} + +void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster, + unsigned int mode) +{ + unsigned int val = 0; + unsigned int offset; + + if (mode == HISI_IPC_PM_ON) + offset = cluster * 4; + else + offset = cluster * 4 + 1; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val); + isb(); + dsb(); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON); +} + +void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF); +} + +void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster) +{ + unsigned int val = 0; + unsigned int offset; + + offset = cluster * 16 + cpu * 4 + 2; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster) +{ + unsigned int val; + unsigned int offset; + + offset = cluster * 4 + 1; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) { + val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val); + } + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_psci_system_off(void) +{ + hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD); +} + +int hisi_ipc_init(void) +{ + ipc_init = 1; + + mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8); + mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8); + return 0; +} diff --git a/plat/hisilicon/hikey/hisi_mcu.c b/plat/hisilicon/hikey/hisi_mcu.c new file mode 100644 index 0000000..ac83bd8 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_mcu.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/console.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <hi6220.h> + +#define MCU_SECTION_MAX 30 + +enum MCU_IMAGE_SEC_TYPE_ENUM { + MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */ + MCU_IMAGE_SEC_TYPE_DATA, /* data section */ + MCU_IMAGE_SEC_TYPE_BUTT +}; + +enum MCU_IMAGE_SEC_LOAD_ENUM { + MCU_IMAGE_SEC_LOAD_STATIC = 0, + MCU_IMAGE_SEC_LOAD_DYNAMIC, + MCU_IMAGE_SEC_LOAD_BUFFER, + MCU_IMAGE_SEC_LOAD_MODEM_ENTRY, + MCU_IMAGE_SEC_LOAD_BUTT +}; + +struct mcu_image_sec { + unsigned short serial; + char type; + char load_attr; + uint32_t src_offset; /* offset in image */ + uint32_t dst_offset; /* offset in memory */ + uint32_t size; +}; + +struct mcu_image_head { + char time_stamp[24]; + uint32_t image_size; + uint32_t secs_num; + struct mcu_image_sec secs[MCU_SECTION_MAX]; +}; + +#define SOC_SRAM_M3_BASE_ADDR (0xF6000000) + +#define MCU_SRAM_SIZE (0x0000C000) +#define MCU_CACHE_SIZE (0x00004000) +#define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE) + +#define MCU_SYS_MEM_ADDR (0x05E00000) +#define MCU_SYS_MEM_SIZE (0x00100000) + +static uint32_t mcu2ap_addr(uint32_t mcu_addr) +{ + if (mcu_addr < MCU_CODE_SIZE) + return (mcu_addr + SOC_SRAM_M3_BASE_ADDR); + else if ((mcu_addr >= MCU_SRAM_SIZE) && + (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE)) + return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR; + else + return mcu_addr; +} + +static int is_binary_header_invalid(struct mcu_image_head *head, + unsigned int length) +{ + /* invalid cases */ + if ((head->image_size == 0) || + (head->image_size > length) || + (head->secs_num > MCU_SECTION_MAX) || + (head->secs_num == 0)) + return 1; + + return 0; +} + +static int is_binary_section_invalid(struct mcu_image_sec *sec, + struct mcu_image_head *head) +{ + unsigned long ap_dst_offset = 0; + + if ((sec->serial >= head->secs_num) || + (sec->src_offset + sec->size > head->image_size)) + return 1; + + if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) || + (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT)) + return 1; + + ap_dst_offset = mcu2ap_addr(sec->dst_offset); + if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) && + (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size)) + return 0; + else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) && + (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size)) + return 0; + else if ((ap_dst_offset >= 0xfff8e000) && + (ap_dst_offset < 0xfff91c00 - sec->size)) + return 0; + + ERROR("%s: mcu destination address invalid.\n", __func__); + ERROR("%s: number=%d, dst offset=%d size=%d\n", + __func__, sec->serial, sec->dst_offset, sec->size); + return 1; +} + +void hisi_mcu_enable_sram(void) +{ + mmio_write_32(AO_SC_PERIPH_CLKEN4, + AO_SC_PERIPH_CLKEN4_HCLK_IPC_S | + AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS); + + /* set register to enable dvfs which is used by mcu */ + mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022); + + /* mcu mem is powered on, need de-assert reset */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N); + + /* enable mcu hclk */ + mmio_write_32(AO_SC_PERIPH_CLKEN4, + AO_SC_PERIPH_CLKEN4_HCLK_MCU | + AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP); +} + +void hisi_mcu_start_run(void) +{ + unsigned int val; + + /* set mcu ddr remap configuration */ + mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR); + + /* de-assert reset for mcu and to run */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N); + + val = mmio_read_32(AO_SC_SYS_CTRL2); + mmio_write_32(AO_SC_SYS_CTRL2, + val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR); + + INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__, + mmio_read_32(AO_SC_SYS_CTRL2)); +} + +int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size) +{ + unsigned int i; + struct mcu_image_head *head; + char *buf; + + head = (struct mcu_image_head *)image_base; + if (is_binary_header_invalid(head, image_size)) { + ERROR("Invalid %s image header.\n", head->time_stamp); + return -1; + } + + buf = (char *)head; + for (i = 0; i < head->secs_num; i++) { + + int *src, *dst; + + /* check the sections */ + if (is_binary_section_invalid(&head->secs[i], head)) { + ERROR("Invalid mcu section.\n"); + return -1; + } + + /* check if the section is static-loaded */ + if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC) + continue; + + /* copy the sections */ + src = (int *)(intptr_t)(buf + head->secs[i].src_offset); + dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset); + + memcpy((void *)dst, (void *)src, head->secs[i].size); + + INFO("%s: mcu sections %d:\n", __func__, i); + INFO("%s: src = 0x%x\n", + __func__, (unsigned int)(uintptr_t)src); + INFO("%s: dst = 0x%x\n", + __func__, (unsigned int)(uintptr_t)dst); + INFO("%s: size = %d\n", __func__, head->secs[i].size); + + INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n", + __func__, (unsigned int)(uintptr_t)src, + src[0], src[1], src[2], src[3]); + INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n", + __func__, (unsigned int)(uintptr_t)dst, + dst[0], dst[1], dst[2], dst[3]); + } + + return 0; +} diff --git a/plat/hisilicon/hikey/hisi_pwrc.c b/plat/hisilicon/hikey/hisi_pwrc.c new file mode 100644 index 0000000..e2e3db7 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_pwrc.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <platform_def.h> + +#include <common/debug.h> +#include <lib/mmio.h> + +#include <hi6220_regs_acpu.h> +#include <hi6220_regs_ao.h> +#include <hisi_ipc.h> +#include <hisi_pwrc.h> +#include <hisi_sram_map.h> + +#define CLUSTER_CORE_COUNT (4) +#define CLUSTER_CORE_MASK ((1 << CLUSTER_CORE_COUNT) - 1) + +void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster, + uintptr_t entry_point) +{ + uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD; + unsigned int i; + + if (!core_entry) { + INFO("%s: core entry point is null!\n", __func__); + return; + } + + i = cluster * CLUSTER_CORE_COUNT + core; + mmio_write_64((uintptr_t)(core_entry + i), entry_point); +} + +void hisi_pwrc_set_cluster_wfi(unsigned int cluster) +{ + unsigned int reg = 0; + + if (cluster == 0) { + reg = mmio_read_32(ACPU_SC_SNOOP_PWD); + reg |= PD_DETECT_START0; + mmio_write_32(ACPU_SC_SNOOP_PWD, reg); + } else if (cluster == 1) { + reg = mmio_read_32(ACPU_SC_SNOOP_PWD); + reg |= PD_DETECT_START1; + mmio_write_32(ACPU_SC_SNOOP_PWD, reg); + } +} + +void hisi_pwrc_enable_debug(unsigned int core, unsigned int cluster) +{ + unsigned int val, enable; + + enable = 1U << (core + PDBGUP_CLUSTER1_SHIFT * cluster); + + /* Enable debug module */ + val = mmio_read_32(ACPU_SC_PDBGUP_MBIST); + mmio_write_32(ACPU_SC_PDBGUP_MBIST, val | enable); + do { + /* RAW barrier */ + val = mmio_read_32(ACPU_SC_PDBGUP_MBIST); + } while (!(val & enable)); +} + +int hisi_pwrc_setup(void) +{ + unsigned int reg, sec_entrypoint; + extern char pm_asm_code[], pm_asm_code_end[]; + extern char v7_asm[], v7_asm_end[]; + + sec_entrypoint = PWRCTRL_ACPU_ASM_CODE_BASE; + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), sec_entrypoint >> 2); + + memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400); + memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm, + v7_asm_end - v7_asm); + + memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code, + pm_asm_code_end - pm_asm_code); + + reg = mmio_read_32(AO_SC_SYS_CTRL1); + /* Remap SRAM address for ACPU */ + reg |= AO_SC_SYS_CTRL1_REMAP_SRAM_AARM | + AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK; + + /* Enable reset signal for watchdog */ + reg |= AO_SC_SYS_CTRL1_AARM_WD_RST_CFG | + AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK; + mmio_write_32(AO_SC_SYS_CTRL1, reg); + + return 0; +} diff --git a/plat/hisilicon/hikey/hisi_pwrc_sram.S b/plat/hisilicon/hikey/hisi_pwrc_sram.S new file mode 100644 index 0000000..62542f2 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_pwrc_sram.S @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <cortex_a53.h> +#include <hi6220.h> +#include <hisi_sram_map.h> + + .global pm_asm_code + .global pm_asm_code_end + .global v7_asm + .global v7_asm_end + +func pm_asm_code _align=3 + mov x0, 0 + msr oslar_el1, x0 + + mrs x0, CORTEX_A53_CPUACTLR_EL1 + bic x0, x0, #(CORTEX_A53_CPUACTLR_EL1_RADIS | \ + CORTEX_A53_CPUACTLR_EL1_L1RADIS) + orr x0, x0, #0x180000 + orr x0, x0, #0xe000 + msr CORTEX_A53_CPUACTLR_EL1, x0 + + mrs x3, actlr_el3 + orr x3, x3, #ACTLR_EL3_L2ECTLR_BIT + msr actlr_el3, x3 + + mrs x3, actlr_el2 + orr x3, x3, #ACTLR_EL2_L2ECTLR_BIT + msr actlr_el2, x3 + + ldr x3, =PWRCTRL_ACPU_ASM_D_ARM_PARA_AD + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 +pen: ldr x4, [x3, x0, LSL #3] + cbz x4, pen + + mov x0, #0x0 + mov x1, #0x0 + mov x2, #0x0 + mov x3, #0x0 + br x4 + + .ltorg + +pm_asm_code_end: +endfunc pm_asm_code + + /* + * By default, all cores in Hi6220 reset with aarch32 mode. + * Now hardcode ARMv7 instructions to execute warm reset for + * switching aarch64 mode. + */ + .align 3 + .section .rodata.v7_asm, "aS" +v7_asm: + .word 0xE1A00000 // nop + .word 0xE3A02003 // mov r2, #3 + .word 0xEE0C2F50 // mcr 15, 0, r2, cr12, cr0, {2} + .word 0xE320F003 // wfi + + .ltorg +v7_asm_end: diff --git a/plat/hisilicon/hikey/hisi_sip_svc.c b/plat/hisilicon/hikey/hisi_sip_svc.c new file mode 100644 index 0000000..3cd1bd0 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_sip_svc.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <common/debug.h> +#include <common/runtime_svc.h> +#include <lib/pmf/pmf.h> +#include <tools_share/uuid.h> + +#include <hisi_sip_svc.h> + +/* Hisi SiP Service UUID */ +DEFINE_SVC_UUID2(hisi_sip_svc_uid, + 0x74df99e5, 0x8276, 0xaa40, 0x9f, 0xf8, + 0xc0, 0x85, 0x52, 0xbc, 0x39, 0x3f); + +static int hisi_sip_setup(void) +{ + if (pmf_setup() != 0) + return 1; + return 0; +} + +/* + * This function handles Hisi defined SiP Calls + */ +static uintptr_t hisi_sip_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + int call_count = 0; + + /* + * Dispatch PMF calls to PMF SMC handler and return its return + * value + */ + if (is_pmf_fid(smc_fid)) { + return pmf_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + switch (smc_fid) { + case HISI_SIP_SVC_CALL_COUNT: + /* PMF calls */ + call_count += PMF_NUM_SMC_CALLS; + + /* State switch call */ + call_count += 1; + + SMC_RET1(handle, call_count); + + case HISI_SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, hisi_sip_svc_uid); + + case HISI_SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, HISI_SIP_SVC_VERSION_MAJOR, HISI_SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented HISI SiP Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } + +} + + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + hisi_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + hisi_sip_setup, + hisi_sip_handler +); diff --git a/plat/hisilicon/hikey/include/hi6220.h b/plat/hisilicon/hikey/include/hi6220.h new file mode 100644 index 0000000..f67ee5c --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6220.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_H +#define HI6220_H + +#include <hi6220_regs_acpu.h> +#include <hi6220_regs_ao.h> +#include <hi6220_regs_peri.h> +#include <hi6220_regs_pin.h> +#include <hi6220_regs_pmctrl.h> + +/******************************************************************************* + * Implementation defined ACTLR_EL2 bit definitions + ******************************************************************************/ +#define ACTLR_EL2_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL2_L2ECTLR_BIT (1 << 5) +#define ACTLR_EL2_L2CTLR_BIT (1 << 4) +#define ACTLR_EL2_CPUECTLR_BIT (1 << 1) +#define ACTLR_EL2_CPUACTLR_BIT (1 << 0) + +/******************************************************************************* + * Implementation defined ACTLR_EL3 bit definitions + ******************************************************************************/ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_L2ECTLR_BIT (1 << 5) +#define ACTLR_EL3_L2CTLR_BIT (1 << 4) +#define ACTLR_EL3_CPUECTLR_BIT (1 << 1) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0xF6E90000 +#define CCI400_SL_IFACE3_CLUSTER_IX 3 +#define CCI400_SL_IFACE4_CLUSTER_IX 4 + +#define DWMMC0_BASE 0xF723D000 + +#define DWUSB_BASE 0xF72C0000 + +#define EDMAC_BASE 0xf7370000 +#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694) +#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6)) +#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1) +#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0) +#define EDMAC_CHANNEL_NUMS 16 + +#define PMUSSI_BASE 0xF8000000 + +#define SP804_TIMER0_BASE 0xF8008000 + +#define GPIO0_BASE 0xF8011000 +#define GPIO1_BASE 0xF8012000 +#define GPIO2_BASE 0xF8013000 +#define GPIO3_BASE 0xF8014000 +#define GPIO4_BASE 0xF7020000 +#define GPIO5_BASE 0xF7021000 +#define GPIO6_BASE 0xF7022000 +#define GPIO7_BASE 0xF7023000 +#define GPIO8_BASE 0xF7024000 +#define GPIO9_BASE 0xF7025000 +#define GPIO10_BASE 0xF7026000 +#define GPIO11_BASE 0xF7027000 +#define GPIO12_BASE 0xF7028000 +#define GPIO13_BASE 0xF7029000 +#define GPIO14_BASE 0xF702A000 +#define GPIO15_BASE 0xF702B000 +#define GPIO16_BASE 0xF702C000 +#define GPIO17_BASE 0xF702D000 +#define GPIO18_BASE 0xF702E000 +#define GPIO19_BASE 0xF702F000 + +#endif /* HI6220_H */ diff --git a/plat/hisilicon/hikey/include/hi6220_regs_acpu.h b/plat/hisilicon/hikey/include/hi6220_regs_acpu.h new file mode 100644 index 0000000..a43db68 --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6220_regs_acpu.h @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_ACPU_H +#define HI6220_REGS_ACPU_H + +#define ACPU_CTRL_BASE 0xF6504000 + +#define ACPU_SC_CPU_CTRL (ACPU_CTRL_BASE + 0x000) +#define ACPU_SC_CPU_STAT (ACPU_CTRL_BASE + 0x008) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2 (1 << 0) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2_SHIFT (0) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0 (1 << 1) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0_SHIFT (1) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1 (1 << 2) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1_SHIFT (2) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2 (1 << 3) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2_SHIFT (3) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3 (1 << 4) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3_SHIFT (4) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2 (1 << 8) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2_SHIFT (8) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI (1 << 9) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI_SHIFT (9) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE0 (1 << 16) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE0_SHIFT (16) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE1 (1 << 17) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE1_SHIFT (17) +#define ACPU_SC_CPU_STAT_CCI400_ACTIVE (1 << 18) +#define ACPU_SC_CPU_STAT_CCI400_ACTIVE_SHIFT (18) +#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD (1 << 20) +#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT (20) + +#define ACPU_SC_CLKEN (ACPU_CTRL_BASE + 0x00c) +#define HPM_L2_1_CLKEN (1 << 9) +#define G_CPU_1_CLKEN (1 << 8) +#define HPM_L2_CLKEN (1 << 1) +#define G_CPU_CLKEN (1 << 0) + +#define ACPU_SC_CLKDIS (ACPU_CTRL_BASE + 0x010) +#define ACPU_SC_CLK_STAT (ACPU_CTRL_BASE + 0x014) +#define ACPU_SC_RSTEN (ACPU_CTRL_BASE + 0x018) +#define SRST_PRESET1_RSTEN (1 << 11) +#define SRST_PRESET0_RSTEN (1 << 10) +#define SRST_CLUSTER1_RSTEN (1 << 9) +#define SRST_CLUSTER0_RSTEN (1 << 8) +#define SRST_L2_HPM_1_RSTEN (1 << 5) +#define SRST_AARM_L2_1_RSTEN (1 << 4) +#define SRST_L2_HPM_0_RSTEN (1 << 3) +#define SRST_AARM_L2_0_RSTEN (1 << 1) +#define SRST_CLUSTER1 (SRST_PRESET1_RSTEN | \ + SRST_CLUSTER1_RSTEN | \ + SRST_L2_HPM_1_RSTEN | \ + SRST_AARM_L2_1_RSTEN) +#define SRST_CLUSTER0 (SRST_PRESET0_RSTEN | \ + SRST_CLUSTER0_RSTEN | \ + SRST_L2_HPM_0_RSTEN | \ + SRST_AARM_L2_0_RSTEN) + +#define ACPU_SC_RSTDIS (ACPU_CTRL_BASE + 0x01c) +#define ACPU_SC_RST_STAT (ACPU_CTRL_BASE + 0x020) +#define ACPU_SC_PDBGUP_MBIST (ACPU_CTRL_BASE + 0x02c) +#define PDBGUP_CLUSTER1_SHIFT 8 + +#define ACPU_SC_VD_CTRL (ACPU_CTRL_BASE + 0x054) +#define ACPU_SC_VD_MASK_PATTERN_CTRL (ACPU_CTRL_BASE + 0x058) +#define ACPU_SC_VD_MASK_PATTERN_VAL (0xCCB << 12) +#define ACPU_SC_VD_MASK_PATTERN_MASK ((0x1 << 13) - 1) + +#define ACPU_SC_VD_DLY_FIXED_CTRL (ACPU_CTRL_BASE + 0x05c) +#define ACPU_SC_VD_DLY_TABLE0_CTRL (ACPU_CTRL_BASE + 0x060) +#define ACPU_SC_VD_DLY_TABLE1_CTRL (ACPU_CTRL_BASE + 0x064) +#define ACPU_SC_VD_DLY_TABLE2_CTRL (ACPU_CTRL_BASE + 0x068) +#define ACPU_SC_VD_HPM_CTRL (ACPU_CTRL_BASE + 0x06c) +#define ACPU_SC_A53_CLUSTER_MTCMOS_EN (ACPU_CTRL_BASE + 0x088) +#define PW_MTCMOS_EN_A53_1_EN (1 << 1) +#define PW_MTCMOS_EN_A53_0_EN (1 << 0) + +#define ACPU_SC_A53_CLUSTER_MTCMOS_STA (ACPU_CTRL_BASE + 0x090) +#define ACPU_SC_A53_CLUSTER_ISO_EN (ACPU_CTRL_BASE + 0x098) +#define PW_ISO_A53_1_EN (1 << 1) +#define PW_ISO_A53_0_EN (1 << 0) + +#define ACPU_SC_A53_CLUSTER_ISO_DIS (ACPU_CTRL_BASE + 0x09c) +#define ACPU_SC_A53_CLUSTER_ISO_STA (ACPU_CTRL_BASE + 0x0a0) +#define ACPU_SC_A53_1_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0b4) +#define ACPU_SC_A53_0_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0bc) +#define ACPU_SC_A53_x_MTCMOS_TIMER(x) ((x) ? ACPU_SC_A53_1_MTCMOS_TIMER : ACPU_SC_A53_0_MTCMOS_TIMER) + +#define ACPU_SC_SNOOP_PWD (ACPU_CTRL_BASE + 0xe4) +#define PD_DETECT_START1 (1 << 16) +#define PD_DETECT_START0 (1 << 0) + +#define ACPU_SC_CPU0_CTRL (ACPU_CTRL_BASE + 0x100) +#define CPU_CTRL_AARCH64_MODE (1 << 7) + +#define ACPU_SC_CPU0_STAT (ACPU_CTRL_BASE + 0x104) +#define ACPU_SC_CPU0_CLKEN (ACPU_CTRL_BASE + 0x108) +#define CPU_CLKEN_HPM (1 << 1) + +#define ACPU_SC_CPU0_CLK_STAT (ACPU_CTRL_BASE + 0x110) + +#define ACPU_SC_CPU0_RSTEN (ACPU_CTRL_BASE + 0x114) +#define ACPU_SC_CPU0_RSTDIS (ACPU_CTRL_BASE + 0x118) +#define ACPU_SC_CPU0_MTCMOS_EN (ACPU_CTRL_BASE + 0x120) +#define CPU_MTCMOS_PW (1 << 0) + +#define ACPU_SC_CPU0_PW_ISOEN (ACPU_CTRL_BASE + 0x130) +#define CPU_PW_ISO (1 << 0) + +#define ACPU_SC_CPU0_PW_ISODIS (ACPU_CTRL_BASE + 0x134) +#define ACPU_SC_CPU0_PW_ISO_STAT (ACPU_CTRL_BASE + 0x138) +#define ACPU_SC_CPU0_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x154) +#define CPU_MTCMOS_TIMER_STA (1 << 0) + +#define ACPU_SC_CPU0_RVBARADDR (ACPU_CTRL_BASE + 0x158) +#define ACPU_SC_CPU1_CTRL (ACPU_CTRL_BASE + 0x200) +#define ACPU_SC_CPU1_STAT (ACPU_CTRL_BASE + 0x204) +#define ACPU_SC_CPU1_CLKEN (ACPU_CTRL_BASE + 0x208) +#define ACPU_SC_CPU1_CLK_STAT (ACPU_CTRL_BASE + 0x210) +#define ACPU_SC_CPU1_RSTEN (ACPU_CTRL_BASE + 0x214) +#define ACPU_SC_CPU1_RSTDIS (ACPU_CTRL_BASE + 0x218) +#define ACPU_SC_CPU1_MTCMOS_EN (ACPU_CTRL_BASE + 0x220) +#define ACPU_SC_CPU1_PW_ISODIS (ACPU_CTRL_BASE + 0x234) +#define ACPU_SC_CPU1_PW_ISO_STAT (ACPU_CTRL_BASE + 0x238) +#define ACPU_SC_CPU1_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x254) +#define ACPU_SC_CPU1_RVBARADDR (ACPU_CTRL_BASE + 0x258) +#define ACPU_SC_CPU2_CTRL (ACPU_CTRL_BASE + 0x300) +#define ACPU_SC_CPU2_STAT (ACPU_CTRL_BASE + 0x304) +#define ACPU_SC_CPU2_CLKEN (ACPU_CTRL_BASE + 0x308) +#define ACPU_SC_CPU2_CLK_STAT (ACPU_CTRL_BASE + 0x310) +#define ACPU_SC_CPU2_RSTEN (ACPU_CTRL_BASE + 0x314) +#define ACPU_SC_CPU2_RSTDIS (ACPU_CTRL_BASE + 0x318) +#define ACPU_SC_CPU2_MTCMOS_EN (ACPU_CTRL_BASE + 0x320) +#define ACPU_SC_CPU2_PW_ISODIS (ACPU_CTRL_BASE + 0x334) +#define ACPU_SC_CPU2_PW_ISO_STAT (ACPU_CTRL_BASE + 0x338) +#define ACPU_SC_CPU2_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x354) +#define ACPU_SC_CPU2_RVBARADDR (ACPU_CTRL_BASE + 0x358) +#define ACPU_SC_CPU3_CTRL (ACPU_CTRL_BASE + 0x400) +#define ACPU_SC_CPU3_STAT (ACPU_CTRL_BASE + 0x404) +#define ACPU_SC_CPU3_CLKEN (ACPU_CTRL_BASE + 0x408) +#define ACPU_SC_CPU3_CLK_STAT (ACPU_CTRL_BASE + 0x410) +#define ACPU_SC_CPU3_RSTEN (ACPU_CTRL_BASE + 0x414) +#define ACPU_SC_CPU3_RSTDIS (ACPU_CTRL_BASE + 0x418) +#define ACPU_SC_CPU3_MTCMOS_EN (ACPU_CTRL_BASE + 0x420) +#define ACPU_SC_CPU3_PW_ISODIS (ACPU_CTRL_BASE + 0x434) +#define ACPU_SC_CPU3_PW_ISO_STAT (ACPU_CTRL_BASE + 0x438) +#define ACPU_SC_CPU3_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x454) +#define ACPU_SC_CPU3_RVBARADDR (ACPU_CTRL_BASE + 0x458) +#define ACPU_SC_CPU4_CTRL (ACPU_CTRL_BASE + 0x500) +#define ACPU_SC_CPU4_STAT (ACPU_CTRL_BASE + 0x504) +#define ACPU_SC_CPU4_CLKEN (ACPU_CTRL_BASE + 0x508) +#define ACPU_SC_CPU4_CLK_STAT (ACPU_CTRL_BASE + 0x510) +#define ACPU_SC_CPU4_RSTEN (ACPU_CTRL_BASE + 0x514) +#define ACPU_SC_CPU4_RSTDIS (ACPU_CTRL_BASE + 0x518) +#define ACPU_SC_CPU4_MTCMOS_EN (ACPU_CTRL_BASE + 0x520) +#define ACPU_SC_CPU4_PW_ISODIS (ACPU_CTRL_BASE + 0x534) +#define ACPU_SC_CPU4_PW_ISO_STAT (ACPU_CTRL_BASE + 0x538) +#define ACPU_SC_CPU4_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x554) +#define ACPU_SC_CPU4_RVBARADDR (ACPU_CTRL_BASE + 0x558) +#define ACPU_SC_CPU5_CTRL (ACPU_CTRL_BASE + 0x600) +#define ACPU_SC_CPU5_STAT (ACPU_CTRL_BASE + 0x604) +#define ACPU_SC_CPU5_CLKEN (ACPU_CTRL_BASE + 0x608) +#define ACPU_SC_CPU5_CLK_STAT (ACPU_CTRL_BASE + 0x610) +#define ACPU_SC_CPU5_RSTEN (ACPU_CTRL_BASE + 0x614) +#define ACPU_SC_CPU5_RSTDIS (ACPU_CTRL_BASE + 0x618) +#define ACPU_SC_CPU5_MTCMOS_EN (ACPU_CTRL_BASE + 0x620) +#define ACPU_SC_CPU5_PW_ISODIS (ACPU_CTRL_BASE + 0x634) +#define ACPU_SC_CPU5_PW_ISO_STAT (ACPU_CTRL_BASE + 0x638) +#define ACPU_SC_CPU5_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x654) +#define ACPU_SC_CPU5_RVBARADDR (ACPU_CTRL_BASE + 0x658) +#define ACPU_SC_CPU6_CTRL (ACPU_CTRL_BASE + 0x700) +#define ACPU_SC_CPU6_STAT (ACPU_CTRL_BASE + 0x704) +#define ACPU_SC_CPU6_CLKEN (ACPU_CTRL_BASE + 0x708) +#define ACPU_SC_CPU6_CLK_STAT (ACPU_CTRL_BASE + 0x710) +#define ACPU_SC_CPU6_RSTEN (ACPU_CTRL_BASE + 0x714) +#define ACPU_SC_CPU6_RSTDIS (ACPU_CTRL_BASE + 0x718) +#define ACPU_SC_CPU6_MTCMOS_EN (ACPU_CTRL_BASE + 0x720) +#define ACPU_SC_CPU6_PW_ISODIS (ACPU_CTRL_BASE + 0x734) +#define ACPU_SC_CPU6_PW_ISO_STAT (ACPU_CTRL_BASE + 0x738) +#define ACPU_SC_CPU6_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x754) +#define ACPU_SC_CPU6_RVBARADDR (ACPU_CTRL_BASE + 0x758) +#define ACPU_SC_CPU7_CTRL (ACPU_CTRL_BASE + 0x800) +#define ACPU_SC_CPU7_STAT (ACPU_CTRL_BASE + 0x804) +#define ACPU_SC_CPU7_CLKEN (ACPU_CTRL_BASE + 0x808) +#define ACPU_SC_CPU7_CLK_STAT (ACPU_CTRL_BASE + 0x810) +#define ACPU_SC_CPU7_RSTEN (ACPU_CTRL_BASE + 0x814) +#define ACPU_SC_CPU7_RSTDIS (ACPU_CTRL_BASE + 0x818) +#define ACPU_SC_CPU7_MTCMOS_EN (ACPU_CTRL_BASE + 0x820) +#define ACPU_SC_CPU7_PW_ISODIS (ACPU_CTRL_BASE + 0x834) +#define ACPU_SC_CPU7_PW_ISO_STAT (ACPU_CTRL_BASE + 0x838) +#define ACPU_SC_CPU7_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x854) +#define ACPU_SC_CPU7_RVBARADDR (ACPU_CTRL_BASE + 0x858) +#define ACPU_SC_CPUx_CTRL(x) ((x < 8) ? (ACPU_SC_CPU0_CTRL + 0x100 * x) : ACPU_SC_CPU0_CTRL) +#define ACPU_SC_CPUx_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_STAT + 0x100 * x) : ACPU_SC_CPU0_STAT) +#define ACPU_SC_CPUx_CLKEN(x) ((x < 8) ? (ACPU_SC_CPU0_CLKEN + 0x100 * x) : ACPU_SC_CPU0_CLKEN) +#define ACPU_SC_CPUx_CLK_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_CLK_STAT + 0x100 * x) : ACPU_SC_CPU0_CLK_STAT) +#define ACPU_SC_CPUx_RSTEN(x) ((x < 8) ? (ACPU_SC_CPU0_RSTEN + 0x100 * x) : ACPU_SC_CPU0_RSTEN) +#define ACPU_SC_CPUx_RSTDIS(x) ((x < 8) ? (ACPU_SC_CPU0_RSTDIS + 0x100 * x) : ACPU_SC_CPU0_RSTDIS) +#define ACPU_SC_CPUx_MTCMOS_EN(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_EN + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_EN) +#define ACPU_SC_CPUx_PW_ISODIS(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISODIS + 0x100 * x) : ACPU_SC_CPU0_PW_ISODIS) +#define ACPU_SC_CPUx_PW_ISO_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISO_STAT + 0x100 * x) : ACPU_SC_CPU0_PW_ISO_STAT) +#define ACPU_SC_CPUx_MTCMOS_TIMER_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_TIMER_STAT + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_TIMER_STAT) +#define ACPU_SC_CPUx_RVBARADDR(x) ((x < 8) ? (ACPU_SC_CPU0_RVBARADDR + 0x100 * x) : ACPU_SC_CPU0_RVBARADDR) + +#define ACPU_SC_CPU_STAT_CLKDIV_VD_MASK (3 << 20) + +#define ACPU_SC_VD_CTRL_TUNE_EN_DIF (1 << 0) +#define ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT (0) +#define ACPU_SC_VD_CTRL_TUNE (1 << 1) +#define ACPU_SC_VD_CTRL_TUNE_SHIFT (1) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF (1 << 7) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT (7) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI (1 << 8) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT (8) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR (1 << 9) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR_SHIFT (9) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN (1 << 10) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT (10) +#define ACPU_SC_VD_CTRL_TUNE_EN_INT (1 << 11) +#define ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT (11) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE0 (1 << 12) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_MASK (0xf << 12) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT (12) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE1 (1 << 16) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_MASK (0xf << 16) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT (16) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE2 (1 << 20) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_MASK (0xf << 20) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT (20) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE3 (1 << 24) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_MASK (0xf << 24) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT (24) +#define ACPU_SC_VD_CTRL_FORCE_CLK_EN (1 << 28) +#define ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT (28) +#define ACPU_SC_VD_CTRL_DIV_EN_DIF (1 << 29) +#define ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT (29) + +#define ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL \ + ((0x1 << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \ + (0x3 << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \ + (0x5 << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \ + (0x6 << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \ + (0x7 << ACPU_SC_VD_CTRL_TUNE_SHIFT)) + +#define ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK \ + ((0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \ + (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \ + (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \ + (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \ + (0x3F << ACPU_SC_VD_CTRL_TUNE_SHIFT)) + +#define ACPU_SC_VD_HPM_CTRL_OSC_DIV (1 << 0) +#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT (0) +#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK (0x000000FF) +#define ACPU_SC_VD_HPM_CTRL_DLY_EXP (1 << 8) +#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT (8) +#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK (0x001FFF00) + +#define HPM_OSC_DIV_VAL \ + (0x56 << ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT) +#define HPM_OSC_DIV_MASK \ + (ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK) + +#define HPM_DLY_EXP_VAL \ + (0xC7A << ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT) +#define HPM_DLY_EXP_MASK \ + (ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK) + +#define ACPU_SC_VD_EN_ASIC_VAL \ + ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \ + (0X0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \ + (0X0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT)) + +#define ACPU_SC_VD_EN_SFT_VAL \ + ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT)) + +#define ACPU_SC_VD_EN_MASK \ + ((0x1 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT)) + +#endif /* HI6220_REGS_ACPU_H */ diff --git a/plat/hisilicon/hikey/include/hi6220_regs_ao.h b/plat/hisilicon/hikey/include/hi6220_regs_ao.h new file mode 100644 index 0000000..614eba2 --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6220_regs_ao.h @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_AO_H +#define HI6220_REGS_AO_H + +#define AO_CTRL_BASE 0xF7800000 + +#define AO_SC_SYS_CTRL0 (AO_CTRL_BASE + 0x000) +#define AO_SC_SYS_CTRL1 (AO_CTRL_BASE + 0x004) +#define AO_SC_SYS_CTRL2 (AO_CTRL_BASE + 0x008) +#define AO_SC_SYS_STAT0 (AO_CTRL_BASE + 0x010) +#define AO_SC_SYS_STAT1 (AO_CTRL_BASE + 0x014) +#define AO_SC_MCU_IMCTRL (AO_CTRL_BASE + 0x018) +#define AO_SC_MCU_IMSTAT (AO_CTRL_BASE + 0x01C) +#define AO_SC_SECONDRY_INT_EN0 (AO_CTRL_BASE + 0x044) +#define AO_SC_SECONDRY_INT_STATR0 (AO_CTRL_BASE + 0x048) +#define AO_SC_SECONDRY_INT_STATM0 (AO_CTRL_BASE + 0x04C) +#define AO_SC_MCU_WKUP_INT_EN6 (AO_CTRL_BASE + 0x054) +#define AO_SC_MCU_WKUP_INT_STATR6 (AO_CTRL_BASE + 0x058) +#define AO_SC_MCU_WKUP_INT_STATM6 (AO_CTRL_BASE + 0x05C) +#define AO_SC_MCU_WKUP_INT_EN5 (AO_CTRL_BASE + 0x064) +#define AO_SC_MCU_WKUP_INT_STATR5 (AO_CTRL_BASE + 0x068) +#define AO_SC_MCU_WKUP_INT_STATM5 (AO_CTRL_BASE + 0x06C) +#define AO_SC_MCU_WKUP_INT_EN4 (AO_CTRL_BASE + 0x094) +#define AO_SC_MCU_WKUP_INT_STATR4 (AO_CTRL_BASE + 0x098) +#define AO_SC_MCU_WKUP_INT_STATM4 (AO_CTRL_BASE + 0x09C) +#define AO_SC_MCU_WKUP_INT_EN0 (AO_CTRL_BASE + 0x0A8) +#define AO_SC_MCU_WKUP_INT_STATR0 (AO_CTRL_BASE + 0x0AC) +#define AO_SC_MCU_WKUP_INT_STATM0 (AO_CTRL_BASE + 0x0B0) +#define AO_SC_MCU_WKUP_INT_EN1 (AO_CTRL_BASE + 0x0B4) +#define AO_SC_MCU_WKUP_INT_STATR1 (AO_CTRL_BASE + 0x0B8) +#define AO_SC_MCU_WKUP_INT_STATM1 (AO_CTRL_BASE + 0x0BC) +#define AO_SC_INT_STATR (AO_CTRL_BASE + 0x0C4) +#define AO_SC_INT_STATM (AO_CTRL_BASE + 0x0C8) +#define AO_SC_INT_CLEAR (AO_CTRL_BASE + 0x0CC) +#define AO_SC_INT_EN_SET (AO_CTRL_BASE + 0x0D0) +#define AO_SC_INT_EN_DIS (AO_CTRL_BASE + 0x0D4) +#define AO_SC_INT_EN_STAT (AO_CTRL_BASE + 0x0D8) +#define AO_SC_INT_STATR1 (AO_CTRL_BASE + 0x0E4) +#define AO_SC_INT_STATM1 (AO_CTRL_BASE + 0x0E8) +#define AO_SC_INT_CLEAR1 (AO_CTRL_BASE + 0x0EC) +#define AO_SC_INT_EN_SET1 (AO_CTRL_BASE + 0x0F0) +#define AO_SC_INT_EN_DIS1 (AO_CTRL_BASE + 0x0F4) +#define AO_SC_INT_EN_STAT1 (AO_CTRL_BASE + 0x0F8) +#define AO_SC_TIMER_EN0 (AO_CTRL_BASE + 0x1D0) +#define AO_SC_TIMER_EN1 (AO_CTRL_BASE + 0x1D4) +#define AO_SC_TIMER_EN4 (AO_CTRL_BASE + 0x1F0) +#define AO_SC_TIMER_EN5 (AO_CTRL_BASE + 0x1F4) +#define AO_SC_MCU_SUBSYS_CTRL0 (AO_CTRL_BASE + 0x400) +#define AO_SC_MCU_SUBSYS_CTRL1 (AO_CTRL_BASE + 0x404) +#define AO_SC_MCU_SUBSYS_CTRL2 (AO_CTRL_BASE + 0x408) +#define AO_SC_MCU_SUBSYS_CTRL3 (AO_CTRL_BASE + 0x40C) +#define AO_SC_MCU_SUBSYS_CTRL4 (AO_CTRL_BASE + 0x410) +#define AO_SC_MCU_SUBSYS_CTRL5 (AO_CTRL_BASE + 0x414) +#define AO_SC_MCU_SUBSYS_CTRL6 (AO_CTRL_BASE + 0x418) +#define AO_SC_MCU_SUBSYS_CTRL7 (AO_CTRL_BASE + 0x41C) +#define AO_SC_MCU_SUBSYS_STAT0 (AO_CTRL_BASE + 0x440) +#define AO_SC_MCU_SUBSYS_STAT1 (AO_CTRL_BASE + 0x444) +#define AO_SC_MCU_SUBSYS_STAT2 (AO_CTRL_BASE + 0x448) +#define AO_SC_MCU_SUBSYS_STAT3 (AO_CTRL_BASE + 0x44C) +#define AO_SC_MCU_SUBSYS_STAT4 (AO_CTRL_BASE + 0x450) +#define AO_SC_MCU_SUBSYS_STAT5 (AO_CTRL_BASE + 0x454) +#define AO_SC_MCU_SUBSYS_STAT6 (AO_CTRL_BASE + 0x458) +#define AO_SC_MCU_SUBSYS_STAT7 (AO_CTRL_BASE + 0x45C) +#define AO_SC_PERIPH_CLKEN4 (AO_CTRL_BASE + 0x630) +#define AO_SC_PERIPH_CLKDIS4 (AO_CTRL_BASE + 0x634) +#define AO_SC_PERIPH_CLKSTAT4 (AO_CTRL_BASE + 0x638) +#define AO_SC_PERIPH_CLKEN5 (AO_CTRL_BASE + 0x63C) +#define AO_SC_PERIPH_CLKDIS5 (AO_CTRL_BASE + 0x640) +#define AO_SC_PERIPH_CLKSTAT5 (AO_CTRL_BASE + 0x644) +#define AO_SC_PERIPH_RSTEN4 (AO_CTRL_BASE + 0x6F0) +#define AO_SC_PERIPH_RSTDIS4 (AO_CTRL_BASE + 0x6F4) +#define AO_SC_PERIPH_RSTSTAT4 (AO_CTRL_BASE + 0x6F8) +#define AO_SC_PERIPH_RSTEN5 (AO_CTRL_BASE + 0x6FC) +#define AO_SC_PERIPH_RSTDIS5 (AO_CTRL_BASE + 0x700) +#define AO_SC_PERIPH_RSTSTAT5 (AO_CTRL_BASE + 0x704) +#define AO_SC_PW_CLKEN0 (AO_CTRL_BASE + 0x800) +#define AO_SC_PW_CLKDIS0 (AO_CTRL_BASE + 0x804) +#define AO_SC_PW_CLK_STAT0 (AO_CTRL_BASE + 0x808) +#define AO_SC_PW_RSTEN0 (AO_CTRL_BASE + 0x810) +#define AO_SC_PW_RSTDIS0 (AO_CTRL_BASE + 0x814) +#define AO_SC_PW_RST_STAT0 (AO_CTRL_BASE + 0x818) +#define AO_SC_PW_ISOEN0 (AO_CTRL_BASE + 0x820) +#define AO_SC_PW_ISODIS0 (AO_CTRL_BASE + 0x824) +#define AO_SC_PW_ISO_STAT0 (AO_CTRL_BASE + 0x828) +#define AO_SC_PW_MTCMOS_EN0 (AO_CTRL_BASE + 0x830) +#define AO_SC_PW_MTCMOS_DIS0 (AO_CTRL_BASE + 0x834) +#define AO_SC_PW_MTCMOS_STAT0 (AO_CTRL_BASE + 0x838) +#define AO_SC_PW_MTCMOS_ACK_STAT0 (AO_CTRL_BASE + 0x83C) +#define AO_SC_PW_MTCMOS_TIMEOUT_STAT0 (AO_CTRL_BASE + 0x840) +#define AO_SC_PW_STAT0 (AO_CTRL_BASE + 0x850) +#define AO_SC_PW_STAT1 (AO_CTRL_BASE + 0x854) +#define AO_SC_SYSTEST_STAT (AO_CTRL_BASE + 0x880) +#define AO_SC_SYSTEST_SLICER_CNT0 (AO_CTRL_BASE + 0x890) +#define AO_SC_SYSTEST_SLICER_CNT1 (AO_CTRL_BASE + 0x894) +#define AO_SC_PW_CTRL1 (AO_CTRL_BASE + 0x8C8) +#define AO_SC_PW_CTRL (AO_CTRL_BASE + 0x8CC) +#define AO_SC_MCPU_VOTEEN (AO_CTRL_BASE + 0x8D0) +#define AO_SC_MCPU_VOTEDIS (AO_CTRL_BASE + 0x8D4) +#define AO_SC_MCPU_VOTESTAT (AO_CTRL_BASE + 0x8D8) +#define AO_SC_MCPU_VOTE_MSK0 (AO_CTRL_BASE + 0x8E0) +#define AO_SC_MCPU_VOTE_MSK1 (AO_CTRL_BASE + 0x8E4) +#define AO_SC_MCPU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x8E8) +#define AO_SC_MCPU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x8EC) +#define AO_SC_PERI_VOTEEN (AO_CTRL_BASE + 0x8F0) +#define AO_SC_PERI_VOTEDIS (AO_CTRL_BASE + 0x8F4) +#define AO_SC_PERI_VOTESTAT (AO_CTRL_BASE + 0x8F8) +#define AO_SC_PERI_VOTE_MSK0 (AO_CTRL_BASE + 0x900) +#define AO_SC_PERI_VOTE_MSK1 (AO_CTRL_BASE + 0x904) +#define AO_SC_PERI_VOTESTAT0_MSK (AO_CTRL_BASE + 0x908) +#define AO_SC_PERI_VOTESTAT1_MSK (AO_CTRL_BASE + 0x90C) +#define AO_SC_ACPU_VOTEEN (AO_CTRL_BASE + 0x910) +#define AO_SC_ACPU_VOTEDIS (AO_CTRL_BASE + 0x914) +#define AO_SC_ACPU_VOTESTAT (AO_CTRL_BASE + 0x918) +#define AO_SC_ACPU_VOTE_MSK0 (AO_CTRL_BASE + 0x920) +#define AO_SC_ACPU_VOTE_MSK1 (AO_CTRL_BASE + 0x924) +#define AO_SC_ACPU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x928) +#define AO_SC_ACPU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x92C) +#define AO_SC_MCU_VOTEEN (AO_CTRL_BASE + 0x930) +#define AO_SC_MCU_VOTEDIS (AO_CTRL_BASE + 0x934) +#define AO_SC_MCU_VOTESTAT (AO_CTRL_BASE + 0x938) +#define AO_SC_MCU_VOTE_MSK0 (AO_CTRL_BASE + 0x940) +#define AO_SC_MCU_VOTE_MSK1 (AO_CTRL_BASE + 0x944) +#define AO_SC_MCU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x948) +#define AO_SC_MCU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x94C) +#define AO_SC_MCU_VOTE1EN (AO_CTRL_BASE + 0x960) +#define AO_SC_MCU_VOTE1DIS (AO_CTRL_BASE + 0x964) +#define AO_SC_MCU_VOTE1STAT (AO_CTRL_BASE + 0x968) +#define AO_SC_MCU_VOTE1_MSK0 (AO_CTRL_BASE + 0x970) +#define AO_SC_MCU_VOTE1_MSK1 (AO_CTRL_BASE + 0x974) +#define AO_SC_MCU_VOTE1STAT0_MSK (AO_CTRL_BASE + 0x978) +#define AO_SC_MCU_VOTE1STAT1_MSK (AO_CTRL_BASE + 0x97C) +#define AO_SC_MCU_VOTE2EN (AO_CTRL_BASE + 0x980) +#define AO_SC_MCU_VOTE2DIS (AO_CTRL_BASE + 0x984) +#define AO_SC_MCU_VOTE2STAT (AO_CTRL_BASE + 0x988) +#define AO_SC_MCU_VOTE2_MSK0 (AO_CTRL_BASE + 0x990) +#define AO_SC_MCU_VOTE2_MSK1 (AO_CTRL_BASE + 0x994) +#define AO_SC_MCU_VOTE2STAT0_MSK (AO_CTRL_BASE + 0x998) +#define AO_SC_MCU_VOTE2STAT1_MSK (AO_CTRL_BASE + 0x99C) +#define AO_SC_VOTE_CTRL (AO_CTRL_BASE + 0x9A0) +#define AO_SC_VOTE_STAT (AO_CTRL_BASE + 0x9A4) +#define AO_SC_ECONUM (AO_CTRL_BASE + 0xF00) +#define AO_SCCHIPID (AO_CTRL_BASE + 0xF10) +#define AO_SCSOCID (AO_CTRL_BASE + 0xF1C) +#define AO_SC_SOC_FPGA_RTL_DEF (AO_CTRL_BASE + 0xFE0) +#define AO_SC_SOC_FPGA_PR_DEF (AO_CTRL_BASE + 0xFE4) +#define AO_SC_SOC_FPGA_RES_DEF0 (AO_CTRL_BASE + 0xFE8) +#define AO_SC_SOC_FPGA_RES_DEF1 (AO_CTRL_BASE + 0xFEC) +#define AO_SC_XTAL_CTRL0 (AO_CTRL_BASE + 0x102) +#define AO_SC_XTAL_CTRL1 (AO_CTRL_BASE + 0x102) +#define AO_SC_XTAL_CTRL3 (AO_CTRL_BASE + 0x103) +#define AO_SC_XTAL_CTRL5 (AO_CTRL_BASE + 0x103) +#define AO_SC_XTAL_STAT0 (AO_CTRL_BASE + 0x106) +#define AO_SC_XTAL_STAT1 (AO_CTRL_BASE + 0x107) +#define AO_SC_EFUSE_CHIPID0 (AO_CTRL_BASE + 0x108) +#define AO_SC_EFUSE_CHIPID1 (AO_CTRL_BASE + 0x108) +#define AO_SC_EFUSE_SYS_CTRL (AO_CTRL_BASE + 0x108) +#define AO_SC_DEBUG_CTRL1 (AO_CTRL_BASE + 0x128) +#define AO_SC_DBG_STAT (AO_CTRL_BASE + 0x12B) +#define AO_SC_ARM_DBG_KEY0 (AO_CTRL_BASE + 0x12B) +#define AO_SC_RESERVED31 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED32 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED33 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED34 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED35 (AO_CTRL_BASE + 0x13B) +#define AO_SC_RESERVED36 (AO_CTRL_BASE + 0x13B) +#define AO_SC_RESERVED37 (AO_CTRL_BASE + 0x13B) +#define AO_SC_RESERVED38 (AO_CTRL_BASE + 0x13B) +#define AO_SC_ALWAYSON_SYS_CTRL0 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL1 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL2 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL3 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL10 (AO_CTRL_BASE + 0x14A) +#define AO_SC_ALWAYSON_SYS_CTRL11 (AO_CTRL_BASE + 0x14A) +#define AO_SC_ALWAYSON_SYS_STAT0 (AO_CTRL_BASE + 0x14C) +#define AO_SC_ALWAYSON_SYS_STAT1 (AO_CTRL_BASE + 0x14C) +#define AO_SC_ALWAYSON_SYS_STAT2 (AO_CTRL_BASE + 0x14C) +#define AO_SC_ALWAYSON_SYS_STAT3 (AO_CTRL_BASE + 0x14C) +#define AO_SC_PWUP_TIME0 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME1 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME2 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME3 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME4 (AO_CTRL_BASE + 0x189) +#define AO_SC_PWUP_TIME5 (AO_CTRL_BASE + 0x189) +#define AO_SC_PWUP_TIME6 (AO_CTRL_BASE + 0x189) +#define AO_SC_PWUP_TIME7 (AO_CTRL_BASE + 0x189) +#define AO_SC_SECURITY_CTRL1 (AO_CTRL_BASE + 0x1C0) +#define AO_SC_SYSTEST_SLICER_CNT0 (AO_CTRL_BASE + 0x890) +#define AO_SC_SYSTEST_SLICER_CNT1 (AO_CTRL_BASE + 0x894) + +#define AO_SC_SYS_CTRL0_MODE_NORMAL 0x004 +#define AO_SC_SYS_CTRL0_MODE_MASK 0x007 + +#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG (1 << 0) +#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM (1 << 1) +#define AO_SC_SYS_CTRL1_EFUSEC_REMAP (1 << 2) +#define AO_SC_SYS_CTRL1_EXT_PLL_SEL (1 << 3) +#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG (1 << 4) +#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG (1 << 6) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG (1 << 7) +#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG (1 << 8) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG (1 << 9) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG (1 << 10) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1 (1 << 11) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT (1 << 12) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT (1 << 13) +#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG (1 << 15) +#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK (1 << 16) +#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK (1 << 17) +#define AO_SC_SYS_CTRL1_EFUSEC_REMAP_MSK (1 << 18) +#define AO_SC_SYS_CTRL1_EXT_PLL_SEL_MSK (1 << 19) +#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG_MSK (1 << 20) +#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG_MSK (1 << 22) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG_MSK (1 << 23) +#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG_MSK (1 << 24) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG_MSK (1 << 25) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG_MSK (1 << 26) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1_MSK (1 << 27) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT_MSK (1 << 28) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT_MSK (1 << 29) +#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG_MSK (1U << 31) + +#define AO_SC_SYS_CTRL2_MCU_SFT_RST_STAT_CLEAR (1 << 26) +#define AO_SC_SYS_CTRL2_MCU_WDG0_RST_STAT_CLEAR (1 << 27) +#define AO_SC_SYS_CTRL2_TSENSOR_RST_STAT_CLEAR (1 << 28) +#define AO_SC_SYS_CTRL2_ACPU_WDG_RST_STAT_CLEAR (1 << 29) +#define AO_SC_SYS_CTRL2_MCU_WDG1_RST_STAT_CLEAR (1 << 30) +#define AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR (1U << 31) + +#define AO_SC_SYS_STAT0_MCU_RST_STAT (1 << 25) +#define AO_SC_SYS_STAT0_MCU_SOFTRST_STAT (1 << 26) +#define AO_SC_SYS_STAT0_MCU_WDGRST_STAT (1 << 27) +#define AO_SC_SYS_STAT0_TSENSOR_HARDRST_STAT (1 << 28) +#define AO_SC_SYS_STAT0_ACPU_WD_GLB_RST_STAT (1 << 29) +#define AO_SC_SYS_STAT0_CM3_WDG1_RST_STAT (1 << 30) +#define AO_SC_SYS_STAT0_GLB_SRST_STAT (1U << 31) + +#define AO_SC_SYS_STAT1_MODE_STATUS (1 << 0) +#define AO_SC_SYS_STAT1_BOOT_SEL_LOCK (1 << 16) +#define AO_SC_SYS_STAT1_FUNC_MODE_LOCK (1 << 17) +#define AO_SC_SYS_STAT1_BOOT_MODE_LOCK (1 << 19) +#define AO_SC_SYS_STAT1_FUN_JTAG_MODE_OUT (1 << 20) +#define AO_SC_SYS_STAT1_SECURITY_BOOT_FLG (1 << 27) +#define AO_SC_SYS_STAT1_EFUSE_NANDBOOT_MSK (1 << 28) +#define AO_SC_SYS_STAT1_EFUSE_NAND_BITWIDE (1 << 29) + +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N (1 << 0) +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N (1 << 1) +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N (1 << 2) +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N (1 << 3) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER0_N (1 << 4) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER1_N (1 << 5) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT0_N (1 << 6) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT1_N (1 << 7) +#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_S_N (1 << 8) +#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_NS_N (1 << 9) +#define AO_SC_PERIPH_RSTDIS4_PRESET_EFUSEC_N (1 << 10) +#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT0_N (1 << 12) +#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT1_N (1 << 13) +#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT2_N (1 << 14) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER0_N (1 << 15) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER1_N (1 << 16) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER2_N (1 << 17) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER3_N (1 << 18) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER4_N (1 << 19) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER5_N (1 << 20) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER6_N (1 << 21) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER7_N (1 << 22) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER8_N (1 << 23) +#define AO_SC_PERIPH_RSTDIS4_PRESET_UART0_N (1 << 24) +#define AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N (1 << 25) +#define AO_SC_PERIPH_RSTDIS4_RESET_RTC1_N (1 << 26) +#define AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N (1 << 27) +#define AO_SC_PERIPH_RSTDIS4_RESET_JTAG_AUTH_N (1 << 28) +#define AO_SC_PERIPH_RSTDIS4_RESET_CS_DAPB_ON_N (1 << 29) +#define AO_SC_PERIPH_RSTDIS4_MDM_SUBSYS_GLB (1 << 30) + +#define AO_SC_PERIPH_CLKEN4_HCLK_MCU (1 << 0) +#define AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP (1 << 3) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER0 (1 << 4) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER1 (1 << 5) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT0 (1 << 6) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT1 (1 << 7) +#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_S (1 << 8) +#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS (1 << 9) +#define AO_SC_PERIPH_CLKEN4_PCLK_EFUSEC (1 << 10) +#define AO_SC_PERIPH_CLKEN4_PCLK_TZPC (1 << 11) +#define AO_SC_PERIPH_CLKEN4_PCLK_WDT0 (1 << 12) +#define AO_SC_PERIPH_CLKEN4_PCLK_WDT1 (1 << 13) +#define AO_SC_PERIPH_CLKEN4_PCLK_WDT2 (1 << 14) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER0 (1 << 15) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER1 (1 << 16) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER2 (1 << 17) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER3 (1 << 18) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER4 (1 << 19) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER5 (1 << 20) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER6 (1 << 21) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER7 (1 << 22) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER8 (1 << 23) +#define AO_SC_PERIPH_CLKEN4_CLK_UART0 (1 << 24) +#define AO_SC_PERIPH_CLKEN4_CLK_RTC0 (1 << 25) +#define AO_SC_PERIPH_CLKEN4_CLK_RTC1 (1 << 26) +#define AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI (1 << 27) +#define AO_SC_PERIPH_CLKEN4_CLK_JTAG_AUTH (1 << 28) +#define AO_SC_PERIPH_CLKEN4_CLK_CS_DAPB_ON (1 << 29) +#define AO_SC_PERIPH_CLKEN4_CLK_PDM (1 << 30) +#define AO_SC_PERIPH_CLKEN4_CLK_SSI_PAD (1U << 31) + +#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU (1 << 0) +#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_CCPU (1 << 1) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_CCPU (1 << 2) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_CCPU (1 << 3) +#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU (1 << 16) +#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_MCU (1 << 17) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_MCU (1 << 18) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_MCU (1 << 19) + +#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_3 0x003 +#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK 0x007 +#define AO_SC_MCU_SUBSYS_CTRL3_CSSYS_CTRL_PROT (1 << 3) +#define AO_SC_MCU_SUBSYS_CTRL3_TCXO_AFC_OEN_CRG (1 << 4) +#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM1 (1 << 8) +#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM0 (1 << 9) +#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_SD (1 << 10) +#define AO_SC_MCU_SUBSYS_CTRL3_MCU_SUBSYS_CTRL3_RESERVED (1 << 11) + +#define PCLK_TIMER1 (1 << 16) +#define PCLK_TIMER0 (1 << 15) + +#endif /* HI6220_REGS_AO_H */ diff --git a/plat/hisilicon/hikey/include/hi6220_regs_peri.h b/plat/hisilicon/hikey/include/hi6220_regs_peri.h new file mode 100644 index 0000000..77236e8 --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6220_regs_peri.h @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_PERI_H +#define HI6220_REGS_PERI_H + +#define PERI_BASE 0xF7030000 + +#define PERI_SC_PERIPH_CTRL1 (PERI_BASE + 0x000) +#define PERI_SC_PERIPH_CTRL2 (PERI_BASE + 0x004) +#define PERI_SC_PERIPH_CTRL3 (PERI_BASE + 0x008) +#define PERI_SC_PERIPH_CTRL4 (PERI_BASE + 0x00c) +#define PERI_SC_PERIPH_CTRL5 (PERI_BASE + 0x010) +#define PERI_SC_PERIPH_CTRL6 (PERI_BASE + 0x014) +#define PERI_SC_PERIPH_CTRL8 (PERI_BASE + 0x018) +#define PERI_SC_PERIPH_CTRL9 (PERI_BASE + 0x01c) +#define PERI_SC_PERIPH_CTRL10 (PERI_BASE + 0x020) +#define PERI_SC_PERIPH_CTRL12 (PERI_BASE + 0x024) +#define PERI_SC_PERIPH_CTRL13 (PERI_BASE + 0x028) +#define PERI_SC_PERIPH_CTRL14 (PERI_BASE + 0x02c) + +#define PERI_SC_DDR_CTRL0 (PERI_BASE + 0x050) +#define PERI_SC_PERIPH_STAT1 (PERI_BASE + 0x094) + +#define PERI_SC_PERIPH_CLKEN0 (PERI_BASE + 0x200) +#define PERI_SC_PERIPH_CLKDIS0 (PERI_BASE + 0x204) +#define PERI_SC_PERIPH_CLKSTAT0 (PERI_BASE + 0x208) +#define PERI_SC_PERIPH_CLKEN1 (PERI_BASE + 0x210) +#define PERI_SC_PERIPH_CLKDIS1 (PERI_BASE + 0x214) +#define PERI_SC_PERIPH_CLKSTAT1 (PERI_BASE + 0x218) +#define PERI_SC_PERIPH_CLKEN2 (PERI_BASE + 0x220) +#define PERI_SC_PERIPH_CLKDIS2 (PERI_BASE + 0x224) +#define PERI_SC_PERIPH_CLKSTAT2 (PERI_BASE + 0x228) +#define PERI_SC_PERIPH_CLKEN3 (PERI_BASE + 0x230) +#define PERI_SC_PERIPH_CLKDIS3 (PERI_BASE + 0x234) +#define PERI_SC_PERIPH_CLKSTAT3 (PERI_BASE + 0x238) +#define PERI_SC_PERIPH_CLKEN8 (PERI_BASE + 0x240) +#define PERI_SC_PERIPH_CLKDIS8 (PERI_BASE + 0x244) +#define PERI_SC_PERIPH_CLKSTAT8 (PERI_BASE + 0x248) +#define PERI_SC_PERIPH_CLKEN9 (PERI_BASE + 0x250) +#define PERI_SC_PERIPH_CLKDIS9 (PERI_BASE + 0x254) +#define PERI_SC_PERIPH_CLKSTAT9 (PERI_BASE + 0x258) +#define PERI_SC_PERIPH_CLKEN10 (PERI_BASE + 0x260) +#define PERI_SC_PERIPH_CLKDIS10 (PERI_BASE + 0x264) +#define PERI_SC_PERIPH_CLKSTAT10 (PERI_BASE + 0x268) +#define PERI_SC_PERIPH_CLKEN12 (PERI_BASE + 0x270) +#define PERI_SC_PERIPH_CLKDIS12 (PERI_BASE + 0x274) +#define PERI_SC_PERIPH_CLKSTAT12 (PERI_BASE + 0x278) + +#define PERI_SC_PERIPH_RSTEN0 (PERI_BASE + 0x300) +#define PERI_SC_PERIPH_RSTDIS0 (PERI_BASE + 0x304) +#define PERI_SC_PERIPH_RSTSTAT0 (PERI_BASE + 0x308) +#define PERI_SC_PERIPH_RSTEN1 (PERI_BASE + 0x310) +#define PERI_SC_PERIPH_RSTDIS1 (PERI_BASE + 0x314) +#define PERI_SC_PERIPH_RSTSTAT1 (PERI_BASE + 0x318) +#define PERI_SC_PERIPH_RSTEN2 (PERI_BASE + 0x320) +#define PERI_SC_PERIPH_RSTDIS2 (PERI_BASE + 0x324) +#define PERI_SC_PERIPH_RSTSTAT2 (PERI_BASE + 0x328) +#define PERI_SC_PERIPH_RSTEN3 (PERI_BASE + 0x330) +#define PERI_SC_PERIPH_RSTDIS3 (PERI_BASE + 0x334) +#define PERI_SC_PERIPH_RSTSTAT3 (PERI_BASE + 0x338) +#define PERI_SC_PERIPH_RSTEN8 (PERI_BASE + 0x340) +#define PERI_SC_PERIPH_RSTDIS8 (PERI_BASE + 0x344) +#define PERI_SC_PERIPH_RSTSTAT8 (PERI_BASE + 0x338) + +#define PERI_SC_CLK_SEL0 (PERI_BASE + 0x400) +#define PERI_SC_CLKCFG8BIT1 (PERI_BASE + 0x494) +#define PERI_SC_CLKCFG8BIT2 (PERI_BASE + 0x498) +#define PERI_SC_RESERVED8_ADDR (PERI_BASE + 0xd04) + +/* PERI_SC_PERIPH_CTRL1 */ +#define PERI_CTRL1_ETR_AXI_CSYSREQ_N (1 << 0) +#define PERI_CTRL1_ETR_AXI_CSYSREQ_N (1 << 0) +#define PERI_CTRL1_HIFI_INT_MASK (1 << 1) +#define PERI_CTRL1_HIFI_ALL_INT_MASK (1 << 2) +#define PERI_CTRL1_ETR_AXI_CSYSREQ_N_MSK (1 << 16) +#define PERI_CTRL1_HIFI_INT_MASK_MSK (1 << 17) +#define PERI_CTRL1_HIFI_ALL_INT_MASK_MSK (1 << 18) + +/* PERI_SC_PERIPH_CTRL2 */ +#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC0 (1 << 0) +#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC1 (1 << 2) +#define PERI_CTRL2_NAND_SYS_MEM_SEL (1 << 6) +#define PERI_CTRL2_G3D_DDRT_AXI_SEL (1 << 7) +#define PERI_CTRL2_GU_MDM_BBP_TESTPIN_SEL (1 << 8) +#define PERI_CTRL2_CODEC_SSI_MASTER_CHECK (1 << 9) +#define PERI_CTRL2_FUNC_TEST_SOFT (1 << 12) +#define PERI_CTRL2_CSSYS_TS_ENABLE (1 << 15) +#define PERI_CTRL2_HIFI_RAMCTRL_S_EMA (1 << 16) +#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAW (1 << 20) +#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAS (1 << 22) +#define PERI_CTRL2_HIFI_RAMCTRL_S_RET1N (1 << 26) +#define PERI_CTRL2_HIFI_RAMCTRL_S_RET2N (1 << 27) +#define PERI_CTRL2_HIFI_RAMCTRL_S_PGEN (1 << 28) + +/* PERI_SC_PERIPH_CTRL3 */ +#define PERI_CTRL3_HIFI_DDR_HARQMEM_ADDR (1 << 0) +#define PERI_CTRL3_HIFI_HARQMEMRMP_EN (1 << 12) +#define PERI_CTRL3_HARQMEM_SYS_MED_SEL (1 << 13) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP1 (1 << 14) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP2 (1 << 16) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP3 (1 << 18) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP4 (1 << 20) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP5 (1 << 22) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP6 (1 << 24) + +/* PERI_SC_PERIPH_CTRL4 */ +#define PERI_CTRL4_PICO_FSELV (1 << 0) +#define PERI_CTRL4_FPGA_EXT_PHY_SEL (1 << 3) +#define PERI_CTRL4_PICO_REFCLKSEL (1 << 4) +#define PERI_CTRL4_PICO_SIDDQ (1 << 6) +#define PERI_CTRL4_PICO_SUSPENDM_SLEEPM (1 << 7) +#define PERI_CTRL4_PICO_OGDISABLE (1 << 8) +#define PERI_CTRL4_PICO_COMMONONN (1 << 9) +#define PERI_CTRL4_PICO_VBUSVLDEXT (1 << 10) +#define PERI_CTRL4_PICO_VBUSVLDEXTSEL (1 << 11) +#define PERI_CTRL4_PICO_VATESTENB (1 << 12) +#define PERI_CTRL4_PICO_SUSPENDM (1 << 14) +#define PERI_CTRL4_PICO_SLEEPM (1 << 15) +#define PERI_CTRL4_BC11_C (1 << 16) +#define PERI_CTRL4_BC11_B (1 << 17) +#define PERI_CTRL4_BC11_A (1 << 18) +#define PERI_CTRL4_BC11_GND (1 << 19) +#define PERI_CTRL4_BC11_FLOAT (1 << 20) +#define PERI_CTRL4_OTG_PHY_SEL (1 << 21) +#define PERI_CTRL4_USB_OTG_SS_SCALEDOWN_MODE (1 << 22) +#define PERI_CTRL4_OTG_DM_PULLDOWN (1 << 24) +#define PERI_CTRL4_OTG_DP_PULLDOWN (1 << 25) +#define PERI_CTRL4_OTG_IDPULLUP (1 << 26) +#define PERI_CTRL4_OTG_DRVBUS (1 << 27) +#define PERI_CTRL4_OTG_SESSEND (1 << 28) +#define PERI_CTRL4_OTG_BVALID (1 << 29) +#define PERI_CTRL4_OTG_AVALID (1 << 30) +#define PERI_CTRL4_OTG_VBUSVALID (1U << 31) + +/* PERI_SC_PERIPH_CTRL5 */ +#define PERI_CTRL5_USBOTG_RES_SEL (1 << 3) +#define PERI_CTRL5_PICOPHY_ACAENB (1 << 4) +#define PERI_CTRL5_PICOPHY_BC_MODE (1 << 5) +#define PERI_CTRL5_PICOPHY_CHRGSEL (1 << 6) +#define PERI_CTRL5_PICOPHY_VDATSRCEND (1 << 7) +#define PERI_CTRL5_PICOPHY_VDATDETENB (1 << 8) +#define PERI_CTRL5_PICOPHY_DCDENB (1 << 9) +#define PERI_CTRL5_PICOPHY_IDDIG (1 << 10) +#define PERI_CTRL5_DBG_MUX (1 << 11) + +/* PERI_SC_PERIPH_CTRL6 */ +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMA (1 << 0) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAW (1 << 4) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAS (1 << 6) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET1N (1 << 10) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET2N (1 << 11) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_PGEN (1 << 12) + +/* PERI_SC_PERIPH_CTRL8 */ +#define PERI_CTRL8_PICOPHY_TXRISETUNE0 (1 << 0) +#define PERI_CTRL8_PICOPHY_TXPREEMPAMPTUNE0 (1 << 2) +#define PERI_CTRL8_PICOPHY_TXRESTUNE0 (1 << 4) +#define PERI_CTRL8_PICOPHY_TXHSSVTUNE0 (1 << 6) +#define PERI_CTRL8_PICOPHY_COMPDISTUNE0 (1 << 8) +#define PERI_CTRL8_PICOPHY_TXPREEMPPULSETUNE0 (1 << 11) +#define PERI_CTRL8_PICOPHY_OTGTUNE0 (1 << 12) +#define PERI_CTRL8_PICOPHY_SQRXTUNE0 (1 << 16) +#define PERI_CTRL8_PICOPHY_TXVREFTUNE0 (1 << 20) +#define PERI_CTRL8_PICOPHY_TXFSLSTUNE0 (1 << 28) + +/* PERI_SC_PERIPH_CTRL9 */ +#define PERI_CTRL9_PICOPLY_TESTCLKEN (1 << 0) +#define PERI_CTRL9_PICOPLY_TESTDATAOUTSEL (1 << 1) +#define PERI_CTRL9_PICOPLY_TESTADDR (1 << 4) +#define PERI_CTRL9_PICOPLY_TESTDATAIN (1 << 8) + +/* + * PERI_SC_PERIPH_CLKEN0 + * PERI_SC_PERIPH_CLKDIS0 + * PERI_SC_PERIPH_CLKSTAT0 + */ +#define PERI_CLK0_MMC0 (1 << 0) +#define PERI_CLK0_MMC1 (1 << 1) +#define PERI_CLK0_MMC2 (1 << 2) +#define PERI_CLK0_NANDC (1 << 3) +#define PERI_CLK0_USBOTG (1 << 4) +#define PERI_CLK0_PICOPHY (1 << 5) +#define PERI_CLK0_PLL (1 << 6) + +/* + * PERI_SC_PERIPH_CLKEN1 + * PERI_SC_PERIPH_CLKDIS1 + * PERI_SC_PERIPH_CLKSTAT1 + */ +#define PERI_CLK1_HIFI (1 << 0) +#define PERI_CLK1_DIGACODEC (1 << 5) + +/* + * PERI_SC_PERIPH_CLKEN2 + * PERI_SC_PERIPH_CLKDIS2 + * PERI_SC_PERIPH_CLKSTAT2 + */ +#define PERI_CLK2_IPF (1 << 0) +#define PERI_CLK2_SOCP (1 << 1) +#define PERI_CLK2_DMAC (1 << 2) +#define PERI_CLK2_SECENG (1 << 3) +#define PERI_CLK2_HPM0 (1 << 5) +#define PERI_CLK2_HPM1 (1 << 6) +#define PERI_CLK2_HPM2 (1 << 7) +#define PERI_CLK2_HPM3 (1 << 8) + +/* + * PERI_SC_PERIPH_CLKEN3 + * PERI_SC_PERIPH_CLKDIS3 + * PERI_SC_PERIPH_CLKSTAT3 + */ +#define PERI_CLK3_CSSYS (1 << 0) +#define PERI_CLK3_I2C0 (1 << 1) +#define PERI_CLK3_I2C1 (1 << 2) +#define PERI_CLK3_I2C2 (1 << 3) +#define PERI_CLK3_I2C3 (1 << 4) +#define PERI_CLK3_UART1 (1 << 5) +#define PERI_CLK3_UART2 (1 << 6) +#define PERI_CLK3_UART3 (1 << 7) +#define PERI_CLK3_UART4 (1 << 8) +#define PERI_CLK3_SSP (1 << 9) +#define PERI_CLK3_PWM (1 << 10) +#define PERI_CLK3_BLPWM (1 << 11) +#define PERI_CLK3_TSENSOR (1 << 12) +#define PERI_CLK3_GPS (1 << 15) +#define PERI_CLK3_TCXO_PAD0 (1 << 16) +#define PERI_CLK3_TCXO_PAD1 (1 << 17) +#define PERI_CLK3_DAPB (1 << 18) +#define PERI_CLK3_HKADC (1 << 19) +#define PERI_CLK3_CODEC_SSI (1 << 20) +#define PERI_CLK3_TZPC_DEP (1 << 21) + +/* + * PERI_SC_PERIPH_CLKEN8 + * PERI_SC_PERIPH_CLKDIS8 + * PERI_SC_PERIPH_CLKSTAT8 + */ +#define PERI_CLK8_RS0 (1 << 0) +#define PERI_CLK8_RS2 (1 << 1) +#define PERI_CLK8_RS3 (1 << 2) +#define PERI_CLK8_MS0 (1 << 3) +#define PERI_CLK8_MS2 (1 << 5) +#define PERI_CLK8_XG2RAM0 (1 << 6) +#define PERI_CLK8_X2SRAM (1 << 7) +#define PERI_CLK8_SRAM (1 << 8) +#define PERI_CLK8_ROM (1 << 9) +#define PERI_CLK8_HARQ (1 << 10) +#define PERI_CLK8_MMU (1 << 11) +#define PERI_CLK8_DDRC (1 << 12) +#define PERI_CLK8_DDRPHY (1 << 13) +#define PERI_CLK8_DDRPHY_REF (1 << 14) +#define PERI_CLK8_X2X_SYSNOC (1 << 15) +#define PERI_CLK8_X2X_CCPU (1 << 16) +#define PERI_CLK8_DDRT (1 << 17) +#define PERI_CLK8_DDRPACK_RS (1 << 18) + +/* + * PERI_SC_PERIPH_CLKEN9 + * PERI_SC_PERIPH_CLKDIS9 + * PERI_SC_PERIPH_CLKSTAT9 + */ +#define PERI_CLK9_CARM_DAP (1 << 0) +#define PERI_CLK9_CARM_ATB (1 << 1) +#define PERI_CLK9_CARM_LBUS (1 << 2) +#define PERI_CLK9_CARM_KERNEL (1 << 3) + +/* + * PERI_SC_PERIPH_CLKEN10 + * PERI_SC_PERIPH_CLKDIS10 + * PERI_SC_PERIPH_CLKSTAT10 + */ +#define PERI_CLK10_IPF_CCPU (1 << 0) +#define PERI_CLK10_SOCP_CCPU (1 << 1) +#define PERI_CLK10_SECENG_CCPU (1 << 2) +#define PERI_CLK10_HARQ_CCPU (1 << 3) +#define PERI_CLK10_IPF_MCU (1 << 16) +#define PERI_CLK10_SOCP_MCU (1 << 17) +#define PERI_CLK10_SECENG_MCU (1 << 18) +#define PERI_CLK10_HARQ_MCU (1 << 19) + +/* + * PERI_SC_PERIPH_CLKEN12 + * PERI_SC_PERIPH_CLKDIS12 + * PERI_SC_PERIPH_CLKSTAT12 + */ +#define PERI_CLK12_HIFI_SRC (1 << 0) +#define PERI_CLK12_MMC0_SRC (1 << 1) +#define PERI_CLK12_MMC1_SRC (1 << 2) +#define PERI_CLK12_MMC2_SRC (1 << 3) +#define PERI_CLK12_SYSPLL_DIV (1 << 4) +#define PERI_CLK12_TPIU_SRC (1 << 5) +#define PERI_CLK12_MMC0_HF (1 << 6) +#define PERI_CLK12_MMC1_HF (1 << 7) +#define PERI_CLK12_PLL_TEST_SRC (1 << 8) +#define PERI_CLK12_CODEC_SOC (1 << 9) +#define PERI_CLK12_MEDIA (1 << 10) + +/* + * PERI_SC_PERIPH_RSTEN0 + * PERI_SC_PERIPH_RSTDIS0 + * PERI_SC_PERIPH_RSTSTAT0 + */ +#define PERI_RST0_MMC0 (1 << 0) +#define PERI_RST0_MMC1 (1 << 1) +#define PERI_RST0_MMC2 (1 << 2) +#define PERI_RST0_NANDC (1 << 3) +#define PERI_RST0_USBOTG_BUS (1 << 4) +#define PERI_RST0_POR_PICOPHY (1 << 5) +#define PERI_RST0_USBOTG (1 << 6) +#define PERI_RST0_USBOTG_32K (1 << 7) + +/* + * PERI_SC_PERIPH_RSTEN1 + * PERI_SC_PERIPH_RSTDIS1 + * PERI_SC_PERIPH_RSTSTAT1 + */ +#define PERI_RST1_HIFI (1 << 0) +#define PERI_RST1_DIGACODEC (1 << 5) + +/* + * PERI_SC_PERIPH_RSTEN2 + * PERI_SC_PERIPH_RSTDIS2 + * PERI_SC_PERIPH_RSTSTAT2 + */ +#define PERI_RST2_IPF (1 << 0) +#define PERI_RST2_SOCP (1 << 1) +#define PERI_RST2_DMAC (1 << 2) +#define PERI_RST2_SECENG (1 << 3) +#define PERI_RST2_ABB (1 << 4) +#define PERI_RST2_HPM0 (1 << 5) +#define PERI_RST2_HPM1 (1 << 6) +#define PERI_RST2_HPM2 (1 << 7) +#define PERI_RST2_HPM3 (1 << 8) + +/* + * PERI_SC_PERIPH_RSTEN3 + * PERI_SC_PERIPH_RSTDIS3 + * PERI_SC_PERIPH_RSTSTAT3 + */ +#define PERI_RST3_CSSYS (1 << 0) +#define PERI_RST3_I2C0 (1 << 1) +#define PERI_RST3_I2C1 (1 << 2) +#define PERI_RST3_I2C2 (1 << 3) +#define PERI_RST3_I2C3 (1 << 4) +#define PERI_RST3_UART1 (1 << 5) +#define PERI_RST3_UART2 (1 << 6) +#define PERI_RST3_UART3 (1 << 7) +#define PERI_RST3_UART4 (1 << 8) +#define PERI_RST3_SSP (1 << 9) +#define PERI_RST3_PWM (1 << 10) +#define PERI_RST3_BLPWM (1 << 11) +#define PERI_RST3_TSENSOR (1 << 12) +#define PERI_RST3_DAPB (1 << 18) +#define PERI_RST3_HKADC (1 << 19) +#define PERI_RST3_CODEC (1 << 20) + +/* + * PERI_SC_PERIPH_RSTEN8 + * PERI_SC_PERIPH_RSTDIS8 + * PERI_SC_PERIPH_RSTSTAT8 + */ +#define PERI_RST8_RS0 (1 << 0) +#define PERI_RST8_RS2 (1 << 1) +#define PERI_RST8_RS3 (1 << 2) +#define PERI_RST8_MS0 (1 << 3) +#define PERI_RST8_MS2 (1 << 5) +#define PERI_RST8_XG2RAM0 (1 << 6) +#define PERI_RST8_X2SRAM_TZMA (1 << 7) +#define PERI_RST8_SRAM (1 << 8) +#define PERI_RST8_HARQ (1 << 10) +#define PERI_RST8_DDRC (1 << 12) +#define PERI_RST8_DDRC_APB (1 << 13) +#define PERI_RST8_DDRPACK_APB (1 << 14) +#define PERI_RST8_DDRT (1 << 17) + +#endif /* HI6220_REGS_PERI_H */ diff --git a/plat/hisilicon/hikey/include/hi6220_regs_pin.h b/plat/hisilicon/hikey/include/hi6220_regs_pin.h new file mode 100644 index 0000000..05620ea --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6220_regs_pin.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_PIN_H +#define HI6220_REGS_PIN_H + +#define IOMG_BASE 0xF7010000 + +#define IOMG_SD_CLK (IOMG_BASE + 0x0C) +#define IOMG_SD_CMD (IOMG_BASE + 0x10) +#define IOMG_SD_DATA0 (IOMG_BASE + 0x14) +#define IOMG_SD_DATA1 (IOMG_BASE + 0x18) +#define IOMG_SD_DATA2 (IOMG_BASE + 0x1C) +#define IOMG_SD_DATA3 (IOMG_BASE + 0x20) +#define IOMG_GPIO24 (IOMG_BASE + 0x140) + +#define IOMG_MUX_FUNC0 0 +#define IOMG_MUX_FUNC1 1 +#define IOMG_MUX_FUNC2 2 + +#define IOCG1_BASE 0xF7010800 +#define IOCG2_BASE 0xF8001800 + +#define IOCG_SD_CLK (IOCG1_BASE + 0x0C) +#define IOCG_SD_CMD (IOCG1_BASE + 0x10) +#define IOCG_SD_DATA0 (IOCG1_BASE + 0x14) +#define IOCG_SD_DATA1 (IOCG1_BASE + 0x18) +#define IOCG_SD_DATA2 (IOCG1_BASE + 0x1C) +#define IOCG_SD_DATA3 (IOCG1_BASE + 0x20) +#define IOCG_GPIO24 (IOCG1_BASE + 0x150) +#define IOCG_GPIO8 (IOCG2_BASE + 0x30) + +#define IOCG_DRIVE_8MA (2 << 4) +#define IOCG_DRIVE_10MA (3 << 4) +#define IOCG_INPUT_16MA 0x64 +#define IOCG_INPUT_12MA 0x54 +#define IOCG_PULLDOWN (1 << 1) +#define IOCG_PULLUP (1 << 0) + +#endif /* HI6220_REGS_PIN_H */ diff --git a/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h b/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h new file mode 100644 index 0000000..404405b --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_PMCTRL_H +#define HI6220_REGS_PMCTRL_H + +#define PMCTRL_BASE 0xF7032000 + +#define PMCTRL_ACPUPLLCTRL (PMCTRL_BASE + 0x000) +#define PMCTRL_ACPUPLLFREQ (PMCTRL_BASE + 0x004) +#define PMCTRL_DDRPLL1CTRL (PMCTRL_BASE + 0x010) +#define PMCTRL_DDRPLL0CTRL (PMCTRL_BASE + 0x030) +#define PMCTRL_MEDPLLCTRL (PMCTRL_BASE + 0x038) +#define PMCTRL_ACPUPLLSEL (PMCTRL_BASE + 0x100) +#define PMCTRL_ACPUCLKDIV (PMCTRL_BASE + 0x104) +#define PMCTRL_ACPUSYSPLLCFG (PMCTRL_BASE + 0x110) +#define PMCTRL_ACPUCLKOFFCFG (PMCTRL_BASE + 0x114) +#define PMCTRL_ACPUPLLFRAC (PMCTRL_BASE + 0x134) +#define PMCTRL_ACPUPMUVOLUPTIME (PMCTRL_BASE + 0x360) +#define PMCTRL_ACPUPMUVOLDNTIME (PMCTRL_BASE + 0x364) +#define PMCTRL_ACPUVOLPMUADDR (PMCTRL_BASE + 0x368) +#define PMCTRL_ACPUVOLUPSTEP (PMCTRL_BASE + 0x36c) +#define PMCTRL_ACPUVOLDNSTEP (PMCTRL_BASE + 0x370) +#define PMCTRL_ACPUDFTVOL (PMCTRL_BASE + 0x374) +#define PMCTRL_ACPUDESTVOL (PMCTRL_BASE + 0x378) +#define PMCTRL_ACPUVOLTTIMEOUT (PMCTRL_BASE + 0x37c) + +#define PMCTRL_ACPUPLLCTRL_EN_CFG (1 << 0) + +#define PMCTRL_ACPUCLKDIV_CPUEXT_CFG_MASK (3 << 0) +#define PMCTRL_ACPUCLKDIV_DDR_CFG_MASK (3 << 8) +#define PMCTRL_ACPUCLKDIV_CPUEXT_STAT_MASK (3 << 16) +#define PMCTRL_ACPUCLKDIV_DDR_STAT_MASK (3 << 24) + +#define PMCTRL_ACPUPLLSEL_ACPUPLL_CFG (1 << 0) +#define PMCTRL_ACPUPLLSEL_ACPUPLL_STAT (1 << 1) +#define PMCTRL_ACPUPLLSEL_SYSPLL_STAT (1 << 2) + +#define PMCTRL_ACPUSYSPLL_CLKDIV_CFG_MASK 0x7 +#define PMCTRL_ACPUSYSPLL_CLKEN_CFG (1 << 4) +#define PMCTRL_ACPUSYSPLL_CLKDIV_SW (3 << 12) + +#define PMCTRL_ACPUSYSPLLCFG_SYSPLL_CLKEN (1 << 4) +#define PMCTRL_ACPUSYSPLLCFG_CLKDIV_MASK (3 << 12) + +#define PMCTRL_ACPUDESTVOL_DEST_VOL_MASK 0x7f +#define PMCTRL_ACPUDESTVOL_CURR_VOL_MASK (0x7f << 8) + +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START (0) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_END (0) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_START (2) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_END (2) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_START (4) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_END (27) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START (28) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_END (28) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_START (29) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_END (29) + +#define SOC_PMCTRL_ACPUPLLFRAC_ADDR(base) ((base) + (0x134)) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START (12) + +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START (0) +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_END (0) +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START (1) +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_END (1) +#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START (2) +#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_END (2) + +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START (0) +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_END (1) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START (8) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_END (9) +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START (16) +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_END (17) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START (24) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_END (25) + +#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START (0) +#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END (6) +#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START (8) +#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_END (14) + +#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START (0) +#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_END (0) + +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_START (0) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_END (2) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START (4) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_END (4) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_START (8) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_END (9) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_START (16) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_END (19) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_START (20) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_END (20) + +#endif /* HI6220_REGS_PMCTRL_H */ diff --git a/plat/hisilicon/hikey/include/hi6553.h b/plat/hisilicon/hikey/include/hi6553.h new file mode 100644 index 0000000..fc991f8 --- /dev/null +++ b/plat/hisilicon/hikey/include/hi6553.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6553_H +#define HI6553_H + +#include <lib/mmio.h> + +#include <hi6220.h> + +#define HI6553_DISABLE6_XO_CLK (PMUSSI_BASE + (0x036 << 2)) + +#define DISABLE6_XO_CLK_BB (1 << 0) +#define DISABLE6_XO_CLK_CONN (1 << 1) +#define DISABLE6_XO_CLK_NFC (1 << 2) +#define DISABLE6_XO_CLK_RF1 (1 << 3) +#define DISABLE6_XO_CLK_RF2 (1 << 4) + +#define HI6553_VERSION_REG (PMUSSI_BASE + (0x000 << 2)) +#define HI6553_IRQ2_MASK (PMUSSI_BASE + (0x008 << 2)) +#define HI6553_ENABLE2_LDO1_8 (PMUSSI_BASE + (0x029 << 2)) +#define HI6553_DISABLE2_LDO1_8 (PMUSSI_BASE + (0x02a << 2)) +#define HI6553_ONOFF_STATUS2_LDO1_8 (PMUSSI_BASE + (0x02b << 2)) +#define HI6553_ENABLE3_LDO9_16 (PMUSSI_BASE + (0x02c << 2)) +#define HI6553_DISABLE3_LDO9_16 (PMUSSI_BASE + (0x02d << 2)) +#define HI6553_ONOFF_STATUS3_LDO9_16 (PMUSSI_BASE + (0x02e << 2)) +#define HI6553_ENABLE4_LDO17_22 (PMUSSI_BASE + (0x02f << 2)) +#define HI6553_DISABLE4_LDO17_22 (PMUSSI_BASE + (0x030 << 2)) +#define HI6553_ONOFF_STATUS4_LDO17_22 (PMUSSI_BASE + (0x031 << 2)) +#define HI6553_PERI_EN_MARK (PMUSSI_BASE + (0x040 << 2)) +#define HI6553_BUCK2_REG1 (PMUSSI_BASE + (0x04a << 2)) +#define HI6553_BUCK2_REG5 (PMUSSI_BASE + (0x04e << 2)) +#define HI6553_BUCK2_REG6 (PMUSSI_BASE + (0x04f << 2)) +#define HI6553_BUCK3_REG3 (PMUSSI_BASE + (0x054 << 2)) +#define HI6553_BUCK3_REG5 (PMUSSI_BASE + (0x056 << 2)) +#define HI6553_BUCK3_REG6 (PMUSSI_BASE + (0x057 << 2)) +#define HI6553_BUCK4_REG2 (PMUSSI_BASE + (0x05b << 2)) +#define HI6553_BUCK4_REG5 (PMUSSI_BASE + (0x05e << 2)) +#define HI6553_BUCK4_REG6 (PMUSSI_BASE + (0x05f << 2)) +#define HI6553_CLK_TOP0 (PMUSSI_BASE + (0x063 << 2)) +#define HI6553_CLK_TOP3 (PMUSSI_BASE + (0x066 << 2)) +#define HI6553_CLK_TOP4 (PMUSSI_BASE + (0x067 << 2)) +#define HI6553_VSET_BUCK2_ADJ (PMUSSI_BASE + (0x06d << 2)) +#define HI6553_VSET_BUCK3_ADJ (PMUSSI_BASE + (0x06e << 2)) +#define HI6553_LDO7_REG_ADJ (PMUSSI_BASE + (0x078 << 2)) +#define HI6553_LDO10_REG_ADJ (PMUSSI_BASE + (0x07b << 2)) +#define HI6553_LDO15_REG_ADJ (PMUSSI_BASE + (0x080 << 2)) +#define HI6553_LDO19_REG_ADJ (PMUSSI_BASE + (0x084 << 2)) +#define HI6553_LDO20_REG_ADJ (PMUSSI_BASE + (0x085 << 2)) +#define HI6553_LDO21_REG_ADJ (PMUSSI_BASE + (0x086 << 2)) +#define HI6553_LDO22_REG_ADJ (PMUSSI_BASE + (0x087 << 2)) +#define HI6553_DR_LED_CTRL (PMUSSI_BASE + (0x098 << 2)) +#define HI6553_DR_OUT_CTRL (PMUSSI_BASE + (0x099 << 2)) +#define HI6553_DR3_ISET (PMUSSI_BASE + (0x09a << 2)) +#define HI6553_DR3_START_DEL (PMUSSI_BASE + (0x09b << 2)) +#define HI6553_DR4_ISET (PMUSSI_BASE + (0x09c << 2)) +#define HI6553_DR4_START_DEL (PMUSSI_BASE + (0x09d << 2)) +#define HI6553_DR345_TIM_CONF0 (PMUSSI_BASE + (0x0a0 << 2)) +#define HI6553_NP_REG_ADJ1 (PMUSSI_BASE + (0x0be << 2)) +#define HI6553_NP_REG_CHG (PMUSSI_BASE + (0x0c0 << 2)) +#define HI6553_BUCK01_CTRL2 (PMUSSI_BASE + (0x0d9 << 2)) +#define HI6553_BUCK0_CTRL1 (PMUSSI_BASE + (0x0dd << 2)) +#define HI6553_BUCK0_CTRL5 (PMUSSI_BASE + (0x0e1 << 2)) +#define HI6553_BUCK0_CTRL7 (PMUSSI_BASE + (0x0e3 << 2)) +#define HI6553_BUCK1_CTRL1 (PMUSSI_BASE + (0x0e8 << 2)) +#define HI6553_BUCK1_CTRL5 (PMUSSI_BASE + (0x0ec << 2)) +#define HI6553_BUCK1_CTRL7 (PMUSSI_BASE + (0x0ef << 2)) +#define HI6553_CLK19M2_600_586_EN (PMUSSI_BASE + (0x0fe << 2)) + +#define LED_START_DELAY_TIME 0x00 +#define LED_ELEC_VALUE 0x07 +#define LED_LIGHT_TIME 0xf0 +#define LED_GREEN_ENABLE (1 << 1) +#define LED_OUT_CTRL 0x00 + +#define PMU_HI6552_V300 0x30 +#define PMU_HI6552_V310 0x31 + +#endif /* HI6553_H */ diff --git a/plat/hisilicon/hikey/include/hikey_def.h b/plat/hisilicon/hikey/include/hikey_def.h new file mode 100644 index 0000000..590700d --- /dev/null +++ b/plat/hisilicon/hikey/include/hikey_def.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY_DEF_H +#define HIKEY_DEF_H + +/* Always assume DDR is 1GB size. */ +#define DDR_BASE 0x0 +#define DDR_SIZE 0x40000000 + +#define DEVICE_BASE 0xF4000000 +#define DEVICE_SIZE 0x05800000 + +/* Memory location options for TSP */ +#define HIKEY_SRAM_ID 0 +#define HIKEY_DRAM_ID 1 + +/* + * DDR for OP-TEE (32MB from 0x3E00000-0x3FFFFFFF) is divided in several + * regions + * - Secure DDR (default is the top 16MB) used by OP-TEE + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR (8MB) reserved for OP-TEE's future use + */ +#define DDR_SEC_SIZE 0x01000000 +#define DDR_SEC_BASE (DDR_BASE + DDR_SIZE - DDR_SEC_SIZE) /* 0x3F000000 */ + +#define DDR_SDP_SIZE 0x00400000 +#define DDR_SDP_BASE (DDR_SEC_BASE - 0x400000 /* align */ - \ + DDR_SDP_SIZE) + +#define SRAM_BASE 0xFFF80000 +#define SRAM_SIZE 0x00012000 + +/* + * PL011 related constants + */ +#define PL011_UART0_BASE 0xF8015000 +#define PL011_UART2_BASE 0xF7112000 +#define PL011_UART3_BASE 0xF7113000 +#define PL011_BAUDRATE 115200 +#define PL011_UART_CLK_IN_HZ 19200000 + +#define HIKEY_USB_DESC_BASE (DDR_BASE + 0x00800000) +#define HIKEY_USB_DESC_SIZE 0x00100000 +#define HIKEY_USB_DATA_BASE (DDR_BASE + 0x10000000) +#define HIKEY_USB_DATA_SIZE 0x10000000 +#define HIKEY_FB_BUFFER_BASE (HIKEY_USB_DATA_BASE) +#define HIKEY_FB_BUFFER_SIZE HIKEY_USB_DATA_SIZE +#define HIKEY_FB_DOWNLOAD_BASE (HIKEY_FB_BUFFER_BASE + \ + HIKEY_FB_BUFFER_SIZE) +#define HIKEY_FB_DOWNLOAD_SIZE HIKEY_USB_DATA_SIZE + +#define HIKEY_USB_DESC_IN_BASE (DDR_BASE + 0x00800000) +#define HIKEY_USB_DESC_IN_SIZE 0x00040000 +#define HIKEY_USB_DESC_EP0_OUT_BASE (HIKEY_USB_DESC_IN_BASE + \ + HIKEY_USB_DESC_IN_SIZE) +#define HIKEY_USB_DESC_EP0_OUT_SIZE 0x00040000 +#define HIKEY_USB_DESC_EPX_OUT_BASE (HIKEY_USB_DESC_EP0_OUT_BASE + \ + HIKEY_USB_DESC_EP0_OUT_SIZE) +#define HIKEY_USB_DESC_EPX_OUT_SIZE 0x00080000 + +#define HIKEY_MMC_DESC_BASE (DDR_BASE + 0x03000000) +#define HIKEY_MMC_DESC_SIZE 0x00100000 + +/* + * HIKEY_MMC_DATA_BASE & HIKEY_MMC_DATA_SIZE are shared between fastboot + * and eMMC driver. Since it could avoid to memory copy. + * So this SRAM region is used twice. First, it's used in BL1 as temporary + * buffer in eMMC driver. Second, it's used by MCU in BL2. The SRAM region + * needs to be clear before used in BL2. + */ +#define HIKEY_MMC_DATA_BASE (DDR_BASE + 0x10000000) +#define HIKEY_MMC_DATA_SIZE 0x20000000 +#define HIKEY_NS_IMAGE_OFFSET (DDR_BASE + 0x35000000) +#define HIKEY_BL1_MMC_DESC_BASE (SRAM_BASE) +#define HIKEY_BL1_MMC_DESC_SIZE 0x00001000 +#define HIKEY_BL1_MMC_DATA_BASE (HIKEY_BL1_MMC_DESC_BASE + \ + HIKEY_BL1_MMC_DESC_SIZE) +#define HIKEY_BL1_MMC_DATA_SIZE 0x0000B000 + +#define EMMC_BASE 0 +#define HIKEY_EMMC_RPMB_BASE (EMMC_BASE + 0) +#define HIKEY_EMMC_RPMB_MAX_SIZE (128 << 10) +#define HIKEY_EMMC_USERDATA_BASE (EMMC_BASE + 0) +#define HIKEY_EMMC_USERDATA_MAX_SIZE (4 << 30) + +/* + * GIC400 interrupt handling related constants + */ +#define IRQ_SEC_PHY_TIMER 29 +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +#endif /* HIKEY_DEF_H */ diff --git a/plat/hisilicon/hikey/include/hikey_layout.h b/plat/hisilicon/hikey/include/hikey_layout.h new file mode 100644 index 0000000..4b8dc53 --- /dev/null +++ b/plat/hisilicon/hikey/include/hikey_layout.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY_LAYOUT_H +#define HIKEY_LAYOUT_H + +/* + * Platform memory map related constants + */ +#define XG2RAM0_BASE 0xF9800000 +#define XG2RAM0_SIZE 0x00400000 + +/* + * BL1 is stored in XG2RAM0_HIRQ that is 784KB large (0xF980_0000~0xF98C_4000). + */ +#define ONCHIPROM_PARAM_BASE (XG2RAM0_BASE + 0x700) +#define LOADER_RAM_BASE (XG2RAM0_BASE + 0x800) +#define BL1_XG2RAM0_OFFSET 0x1000 + +/* + * BL1 specific defines. + * + * Both loader and BL1_RO region stay in SRAM since they are used to simulate + * ROM. + * Loader is used to switch Hi6220 SoC from 32-bit to 64-bit mode. + * + * ++++++++++ 0xF980_0000 + * + loader + + * ++++++++++ 0xF980_1000 + * + BL1_RO + + * ++++++++++ 0xF981_8000 + * + BL1_RW + + * ++++++++++ 0xF989_8000 + */ +#define BL1_RO_BASE (XG2RAM0_BASE + BL1_XG2RAM0_OFFSET) +#define BL1_RO_LIMIT (XG2RAM0_BASE + 0x18000) +#define BL1_RW_BASE (BL1_RO_LIMIT) /* 0xf981_8000 */ +#define BL1_RW_SIZE (0x00080000) +#define BL1_RW_LIMIT (0xF9898000) + +/* + * Non-Secure BL1U specific defines. + */ +#define NS_BL1U_BASE (0xf9828000) +#define NS_BL1U_SIZE (0x00010000) +#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE) + +/* + * BL2 specific defines. + * + * Both loader and BL2 region stay in SRAM. + * Loader is used to switch Hi6220 SoC from 32-bit to 64-bit mode. + * + * ++++++++++ 0xF980_0000 + * + loader + + * ++++++++++ 0xF980_1000 + * + BL2 + + * ++++++++++ 0xF983_0000 + */ +#define BL2_BASE (BL1_RO_BASE) /* 0xf980_1000 */ +#define BL2_LIMIT (0xF9830000) /* 0xf983_0000 */ + +/* + * SCP_BL2 specific defines. + * In HiKey, SCP_BL2 means MCU firmware. It's loaded into the temporary buffer + * at 0x0100_0000. Then BL2 will parse the sections and loaded them into + * predefined separated buffers. + */ +#define SCP_BL2_BASE (DDR_BASE + 0x01000000) +#define SCP_BL2_LIMIT (SCP_BL2_BASE + 0x00100000) +#define SCP_BL2_SIZE (SCP_BL2_LIMIT - SCP_BL2_BASE) + +/* + * BL31 specific defines. + */ +#define BL31_BASE (0xF9858000) /* 0xf985_8000 */ +#define BL31_LIMIT (0xF9898000) + +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM or SRAM. + */ +#define BL32_SRAM_BASE BL31_LIMIT +#define BL32_SRAM_LIMIT (BL31_LIMIT+0x80000) /* 512K */ + +#define BL32_DRAM_BASE DDR_SEC_BASE +#define BL32_DRAM_LIMIT (DDR_SEC_BASE+DDR_SEC_SIZE) + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define HIKEY_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - HIKEY_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */ +#define HIKEY_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */ +#endif + +#if (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_SRAM_ID) +#define TSP_SEC_MEM_BASE BL32_SRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_SRAM_LIMIT - BL32_SRAM_BASE) +#define BL32_BASE BL32_SRAM_BASE +#define BL32_LIMIT BL32_SRAM_LIMIT +#else +#error "Currently unsupported HIKEY_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifdef __aarch64__ +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#endif /* HIKEY_LAYOUT_H */ diff --git a/plat/hisilicon/hikey/include/hisi_ipc.h b/plat/hisilicon/hikey/include/hisi_ipc.h new file mode 100644 index 0000000..b0c0ae8 --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_ipc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_IPC_H +#define HISI_IPC_H + +#define HISI_IPC_CORE_ACPU 0x0 + +#define HISI_IPC_MCU_INT_SRC_ACPU0_PD 10 +#define HISI_IPC_MCU_INT_SRC_ACPU1_PD 11 +#define HISI_IPC_MCU_INT_SRC_ACPU2_PD 12 +#define HISI_IPC_MCU_INT_SRC_ACPU3_PD 13 +#define HISI_IPC_MCU_INT_SRC_ACPU_PD 16 +#define HISI_IPC_MCU_INT_SRC_ACPU4_PD 26 +#define HISI_IPC_MCU_INT_SRC_ACPU5_PD 27 +#define HISI_IPC_MCU_INT_SRC_ACPU6_PD 28 +#define HISI_IPC_MCU_INT_SRC_ACPU7_PD 29 + +#define HISI_IPC_SEM_CPUIDLE 27 +#define HISI_IPC_INT_SRC_NUM 32 + +#define HISI_IPC_PM_ON 0 +#define HISI_IPC_PM_OFF 1 + +#define HISI_IPC_OK (0) +#define HISI_IPC_ERROR (-1) + +#define HISI_IPC_BASE_ADDR (0xF7510000) +#define HISI_IPC_CPU_RAW_INT_ADDR (0xF7510420) +#define HISI_IPC_ACPU_CTRL(i) (0xF7510800 + (i << 3)) + +void hisi_ipc_spin_lock(unsigned int signal); +void hisi_ipc_spin_unlock(unsigned int signal); +void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster); +void hisi_ipc_psci_system_off(void); +int hisi_ipc_init(void); + +#endif /* HISI_IPC_H */ diff --git a/plat/hisilicon/hikey/include/hisi_mcu.h b/plat/hisilicon/hikey/include/hisi_mcu.h new file mode 100644 index 0000000..731c51a --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_mcu.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_MCU_H +#define HISI_MCU_H + +#include <stdint.h> + +extern void hisi_mcu_enable_sram(void); +extern void hisi_mcu_start_run(void); +extern int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size); + +#endif /* HISI_MCU_H */ diff --git a/plat/hisilicon/hikey/include/hisi_pwrc.h b/plat/hisilicon/hikey/include/hisi_pwrc.h new file mode 100644 index 0000000..cbb4651 --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_pwrc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_PWRC_H +#define HISI_PWRC_H + +#ifndef __ASSEMBLER__ + +void hisi_pwrc_set_cluster_wfi(unsigned int id); +void hisi_pwrc_set_core_bx_addr(unsigned int core, + unsigned int cluster, + uintptr_t entry_point); +void hisi_pwrc_enable_debug(unsigned int core, + unsigned int cluster); +int hisi_pwrc_setup(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* HISI_PWRC_H */ diff --git a/plat/hisilicon/hikey/include/hisi_sip_svc.h b/plat/hisilicon/hikey/include/hisi_sip_svc.h new file mode 100644 index 0000000..a1fad7a --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_sip_svc.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_SIP_SVC_H +#define HISI_SIP_SVC_H + +/* SMC function IDs for SiP Service queries */ + +#define HISI_SIP_SVC_CALL_COUNT 0x8200ff00 +#define HISI_SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define HISI_SIP_SVC_VERSION 0x8200ff03 + +/* HISI SiP Service Calls version numbers */ +#define HISI_SIP_SVC_VERSION_MAJOR 0x0 +#define HISI_SIP_SVC_VERSION_MINOR 0x1 + +#endif /* HISI_SIP_SVC_H */ diff --git a/plat/hisilicon/hikey/include/hisi_sram_map.h b/plat/hisilicon/hikey/include/hisi_sram_map.h new file mode 100644 index 0000000..f93e418 --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_sram_map.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_SRAM_MAP_H +#define HISI_SRAM_MAP_H + +/* + * SRAM Memory Region Layout + * + * +-----------------------+ + * | Low Power Mode | 7KB + * +-----------------------+ + * | Secure OS | 64KB + * +-----------------------+ + * | Software Flag | 1KB + * +-----------------------+ + * + */ + +#define SOC_SRAM_OFF_BASE_ADDR (0xFFF80000) + +/* PM Section: 7KB */ +#define SRAM_PM_ADDR (SOC_SRAM_OFF_BASE_ADDR) +#define SRAM_PM_SIZE (0x00001C00) + +/* TEE OS Section: 64KB */ +#define SRAM_TEEOS_ADDR (SRAM_PM_ADDR + SRAM_PM_SIZE) +#define SRAM_TEEOS_SIZE (0x00010000) + +/* General Use Section: 1KB */ +#define SRAM_GENERAL_ADDR (SRAM_TEEOS_ADDR + SRAM_TEEOS_SIZE) +#define SRAM_GENERAL_SIZE (0x00000400) + +/* + * General Usage Section Layout: + * + * +-----------------------+ + * | AP boot flag | 64B + * +-----------------------+ + * | DICC flag | 32B + * +-----------------------+ + * | Soft flag | 256B + * +-----------------------+ + * | Thermal flag | 128B + * +-----------------------+ + * | CSHELL | 4B + * +-----------------------+ + * | Uart Switching | 4B + * +-----------------------+ + * | ICC | 1024B + * +-----------------------+ + * | Memory Management | 1024B + * +-----------------------+ + * | IFC | 32B + * +-----------------------+ + * | HIFI | 32B + * +-----------------------+ + * | DDR capacity | 4B + * +-----------------------+ + * | Reserved | + * +-----------------------+ + * + */ + +/* App Core Boot Flags */ +#define MEMORY_AXI_ACPU_START_ADDR (SRAM_GENERAL_ADDR) +#define MEMORY_AXI_ACPU_START_SIZE (64) + +#define MEMORY_AXI_SRESET_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0000) +#define MEMORY_AXI_SECOND_CPU_BOOT_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0004) +#define MEMORY_AXI_READY_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0008) +#define MEMORY_AXI_FASTBOOT_ENTRY_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x000C) +#define MEMORY_AXI_PD_CHARGE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0010) +#define MEMORY_AXI_DBG_ALARM_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0014) +#define MEMORY_AXI_CHIP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0018) +#define MEMORY_AXI_BOARD_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x001C) +#define MEMORY_AXI_BOARD_ID_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0020) +#define MEMORY_AXI_CHARGETYPE_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0024) +#define MEMORY_AXI_COLD_START_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0028) +#define MEMORY_AXI_ANDROID_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x002C) +#define MEMORY_AXI_ACPU_WDTRST_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0030) +#define MEMORY_AXI_ABNRST_BITMAP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0034) +#define MEMORY_AXI_32K_CLK_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0038) +#define AXI_MODEM_PANIC_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x003C) +#define AXI_MODEM_PANIC_FLAG (0x68697369) +#define MEMORY_AXI_ACPU_END_ADDR (AXI_MODEM_PANIC_FLAG_ADDR + 4) + +/* DICC Flags */ +#define MEMORY_AXI_DICC_ADDR (MEMORY_AXI_ACPU_START_ADDR + MEMORY_AXI_ACPU_START_SIZE) +#define MEMORY_AXI_DICC_SIZE (32) + +#define MEMORY_AXI_SOFT_FLAG_ADDR (MEMORY_AXI_DICC_ADDR + MEMORY_AXI_DICC_SIZE) +#define MEMORY_AXI_SOFT_FLAG_SIZE (256) + +/* Thermal Flags */ +#define MEMORY_AXI_TEMP_PROTECT_ADDR (MEMORY_AXI_SOFT_FLAG_ADDR + MEMORY_AXI_SOFT_FLAG_SIZE) +#define MEMORY_AXI_TEMP_PROTECT_SIZE (128) + +/* CSHELL */ +#define MEMORY_AXI_USB_CSHELL_ADDR (MEMORY_AXI_TEMP_PROTECT_ADDR + MEMORY_AXI_TEMP_PROTECT_SIZE) +#define MEMORY_AXI_USB_CSHELL_SIZE (4) + +/* Uart and A/C Shell Switch Flags */ +#define MEMORY_AXI_UART_INOUT_ADDR (MEMORY_AXI_USB_CSHELL_ADDR + MEMORY_AXI_USB_CSHELL_SIZE) +#define MEMORY_AXI_UART_INOUT_SIZE (4) + +/* IFC Flags */ +#define MEMORY_AXI_IFC_ADDR (MEMORY_AXI_UART_INOUT_ADDR + MEMORY_AXI_UART_INOUT_SIZE) +#define MEMORY_AXI_IFC_SIZE (32) + +/* HIFI Data */ +#define MEMORY_AXI_HIFI_ADDR (MEMORY_AXI_IFC_ADDR + MEMORY_AXI_IFC_SIZE) +#define MEMORY_AXI_HIFI_SIZE (32) + +/* CONFIG Flags */ +#define MEMORY_AXI_CONFIG_ADDR (MEMORY_AXI_HIFI_ADDR + MEMORY_AXI_HIFI_SIZE) +#define MEMORY_AXI_CONFIG_SIZE (32) + +/* DDR Capacity Flags */ +#define MEMORY_AXI_DDR_CAPACITY_ADDR (MEMORY_AXI_CONFIG_ADDR + MEMORY_AXI_CONFIG_SIZE) +#define MEMORY_AXI_DDR_CAPACITY_SIZE (4) + +/* USB Shell Flags */ +#define MEMORY_AXI_USB_SHELL_FLAG_ADDR (MEMORY_AXI_DDR_CAPACITY_ADDR + MEMORY_AXI_DDR_CAPACITY_SIZE) +#define MEMORY_AXI_USB_SHELL_FLAG_SIZE (4) + +/* MCU WDT Switch Flag */ +#define MEMORY_AXI_MCU_WDT_FLAG_ADDR (MEMORY_AXI_USB_SHELL_FLAG_ADDR + MEMORY_AXI_USB_SHELL_FLAG_SIZE) +#define MEMORY_AXI_MCU_WDT_FLAG_SIZE (4) + +/* TLDSP Mailbox MNTN */ +#define SRAM_DSP_MNTN_INFO_ADDR (MEMORY_AXI_MCU_WDT_FLAG_ADDR + MEMORY_AXI_MCU_WDT_FLAG_SIZE) +#define SRAM_DSP_MNTN_SIZE (32) + +/* TLDSP ARM Mailbox Protect Flag */ +#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR (SRAM_DSP_MNTN_INFO_ADDR + SRAM_DSP_MNTN_SIZE) +#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE (4) + +/* RTT Sleep Flag */ +#define SRAM_RTT_SLEEP_FLAG_ADDR (SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR + SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE) +#define SRAM_RTT_SLEEP_FLAG_SIZE (32) + +/* LDSP Awake Flag */ +#define MEMORY_AXI_LDSP_AWAKE_ADDR (SRAM_RTT_SLEEP_FLAG_ADDR + SRAM_RTT_SLEEP_FLAG_SIZE) +#define MEMORY_AXI_LDSP_AWAKE_SIZE (4) + +#define NVUPDATE_SUCCESS 0x5555AAAA +#define NVUPDATE_FAILURE 0xAAAA5555 + +/* + * Low Power Mode Region + */ +#define PWRCTRL_ACPU_ASM_SPACE_ADDR (SRAM_PM_ADDR) +#define PWRCTRL_ACPU_ASM_SPACE_SIZE (SRAM_PM_SIZE) + +#define PWRCTRL_ACPU_ASM_MEM_BASE (PWRCTRL_ACPU_ASM_SPACE_ADDR) +#define PWRCTRL_ACPU_ASM_MEM_SIZE (PWRCTRL_ACPU_ASM_SPACE_SIZE) +#define PWRCTRL_ACPU_ASM_CODE_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0x200) +#define PWRCTRL_ACPU_ASM_DATA_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0xE00) +#define PWRCTRL_ACPU_ASM_DATA_SIZE (0xE00) + +#define PWRCTRL_ACPU_ASM_D_C0_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE) +#define PWRCTRL_ACPU_ASM_D_C0_MMU_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0) +#define PWRCTRL_ACPU_ASM_D_ARM_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0x20) + +#define PWRCTRL_ACPU_ASM_D_COMM_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE + 0x700) + +#define PWRCTRL_ACPU_REBOOT (PWRCTRL_ACPU_ASM_D_COMM_ADDR) +#define PWRCTRL_ACPU_REBOOT_SIZE (0x200) +#define PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR (PWRCTRL_ACPU_REBOOT + PWRCTRL_ACPU_REBOOT_SIZE) +#define PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE (4) +#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR (PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR + PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE) +#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE (4) +#define EXCH_A_CORE_POWRCTRL_CONV_ADDR (PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR + PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE) +#define EXCH_A_CORE_POWRCTRL_CONV_SIZE (4) + +/* + * Below region memory mapping is: + * 4 + 12 + 16 + 28 + 28 + 16 + 28 + 12 + 24 + 20 + 64 + + * 4 + 4 + 4 + 4 + 12 + 4 + 4 + 4 + 4 + 16 + 4 + 0x2BC + + * 24 + 20 + 12 + 16 + */ + +#define MEMORY_AXI_CPU_IDLE_ADDR (EXCH_A_CORE_POWRCTRL_CONV_ADDR + EXCH_A_CORE_POWRCTRL_CONV_SIZE) +#define MEMORY_AXI_CPU_IDLE_SIZE (4) + +#define MEMORY_AXI_CUR_FREQ_ADDR (MEMORY_AXI_CPU_IDLE_ADDR + MEMORY_AXI_CPU_IDLE_SIZE) +#define MEMORY_AXI_CUR_FREQ_SIZE (12) + +#define MEMORY_AXI_ACPU_FREQ_VOL_ADDR (MEMORY_AXI_CUR_FREQ_ADDR + MEMORY_AXI_CUR_FREQ_SIZE) +#define MEMORY_AXI_ACPU_FREQ_VOL_SIZE (16 + 28 + 28) + +#define MEMORY_AXI_DDR_FREQ_VOL_ADDR (MEMORY_AXI_ACPU_FREQ_VOL_ADDR + MEMORY_AXI_ACPU_FREQ_VOL_SIZE) +#define MEMORY_AXI_DDR_FREQ_VOL_SIZE (16 + 28) + +#define MEMORY_AXI_ACPU_FIQ_TEST_ADDR (MEMORY_AXI_DDR_FREQ_VOL_ADDR + MEMORY_AXI_DDR_FREQ_VOL_SIZE) +#define MEMORY_AXI_ACPU_FIQ_TEST_SIZE (12) + +#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_TEST_ADDR + MEMORY_AXI_ACPU_FIQ_TEST_SIZE) +#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE (24) + +#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE) +#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE (20) + +#define MEMORY_FREQDUMP_ADDR (MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE) +#define MEMORY_FREQDUMP_SIZE (64) + +#define MEMORY_AXI_CCPU_LOG_ADDR (MEMORY_FREQDUMP_ADDR + MEMORY_FREQDUMP_SIZE) +#define MEMORY_AXI_CCPU_LOG_SIZE (4) + +#define MEMORY_AXI_MCU_LOG_ADDR (MEMORY_AXI_CCPU_LOG_ADDR + MEMORY_AXI_CCPU_LOG_SIZE) +#define MEMORY_AXI_MCU_LOG_SIZE (4) + +#define MEMORY_AXI_SEC_CORE_BOOT_ADDR (MEMORY_AXI_MCU_LOG_ADDR + MEMORY_AXI_MCU_LOG_SIZE) +#define MEMORY_AXI_SEC_CORE_BOOT_SIZE (4) + +#define MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR (MEMORY_AXI_SEC_CORE_BOOT_ADDR + MEMORY_AXI_SEC_CORE_BOOT_SIZE) +#define MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE (0x4) + +#define POLICY_AREA_RESERVED (MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR + MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE) +#define POLICY_AREA_RESERVED_SIZE (12) + +#define DDR_POLICY_VALID_MAGIC (POLICY_AREA_RESERVED + POLICY_AREA_RESERVED_SIZE) +#define DDR_POLICY_VALID_MAGIC_SIZE (4) + +#define DDR_POLICY_MAX_NUM (DDR_POLICY_VALID_MAGIC + DDR_POLICY_VALID_MAGIC_SIZE) +#define DDR_POLICY_MAX_NUM_SIZE (4) + +#define DDR_POLICY_SUPPORT_NUM (DDR_POLICY_MAX_NUM + DDR_POLICY_MAX_NUM_SIZE) +#define DDR_POLICY_SUPPORT_NUM_SIZE (4) + +#define DDR_POLICY_CUR_POLICY (DDR_POLICY_SUPPORT_NUM + DDR_POLICY_SUPPORT_NUM_SIZE) +#define DDR_POLICY_CUR_POLICY_SIZE (4) + +#define ACPU_POLICY_VALID_MAGIC (DDR_POLICY_CUR_POLICY + DDR_POLICY_CUR_POLICY_SIZE) +#define ACPU_POLICY_VALID_MAGIC_SIZE (4) + +#define ACPU_POLICY_MAX_NUM (ACPU_POLICY_VALID_MAGIC + ACPU_POLICY_VALID_MAGIC_SIZE) +#define ACPU_POLICY_MAX_NUM_SIZE (4) + +#define ACPU_POLICY_SUPPORT_NUM (ACPU_POLICY_MAX_NUM + ACPU_POLICY_MAX_NUM_SIZE) +#define ACPU_POLICY_SUPPORT_NUM_SIZE (4) + +#define ACPU_POLICY_CUR_POLICY (ACPU_POLICY_SUPPORT_NUM + ACPU_POLICY_SUPPORT_NUM_SIZE) +#define ACPU_POLICY_CUR_POLICY_SIZE (4) + +#define LPDDR_OPTION_ADDR (ACPU_POLICY_CUR_POLICY + ACPU_POLICY_CUR_POLICY_SIZE) +#define LPDDR_OPTION_SIZE (4) + +#define MEMORY_AXI_DDR_DDL_ADDR (LPDDR_OPTION_ADDR + LPDDR_OPTION_SIZE) +#define MEMORY_AXI_DDR_DDL_SIZE (0x2BC) + +#define DDR_TEST_DFS_ADDR (MEMORY_AXI_DDR_DDL_ADDR + MEMORY_AXI_DDR_DDL_SIZE) +#define DDR_TEST_DFS_ADDR_SIZE (4) + +#define DDR_TEST_DFS_TIMES_ADDR (DDR_TEST_DFS_ADDR + DDR_TEST_DFS_ADDR_SIZE) +#define DDR_TEST_DFS_TIMES_ADDR_SIZE (4) + +#define DDR_TEST_QOS_ADDR (DDR_TEST_DFS_TIMES_ADDR + DDR_TEST_DFS_TIMES_ADDR_SIZE) +#define DDR_TEST_QOS_ADDR_SIZE (4) + +#define DDR_TEST_FUN_ADDR (DDR_TEST_QOS_ADDR + DDR_TEST_QOS_ADDR_SIZE) +#define DDR_TEST_FUN_ADDR_SIZE (4) + +#define BOARD_TYPE_ADDR (DDR_TEST_FUN_ADDR + DDR_TEST_FUN_ADDR_SIZE) +#define BOARD_ADDR_SIZE (4) +#define DDR_DFS_FREQ_ADDR (BOARD_TYPE_ADDR + BOARD_ADDR_SIZE) +#define DDR_DFS_FREQ_SIZE (4) + +#define DDR_PASR_ADDR (DDR_DFS_FREQ_ADDR + DDR_DFS_FREQ_SIZE) +#define DDR_PASR_SIZE (20) + +#define ACPU_DFS_FREQ_ADDR (DDR_PASR_ADDR + DDR_PASR_SIZE) +#define ACPU_DFS_FREQ_ADDR_SIZE (12) + +#define ACPU_CHIP_MAX_FREQ (ACPU_DFS_FREQ_ADDR + ACPU_DFS_FREQ_ADDR_SIZE) +#define ACPU_CHIP_MAX_FREQ_SIZE (4) + +#define MEMORY_MEDPLL_STATE_ADDR (ACPU_CHIP_MAX_FREQ + ACPU_CHIP_MAX_FREQ_SIZE) +#define MEMORY_MEDPLL_STATE_SIZE (8) + +#define MEMORY_CCPU_LOAD_FLAG_ADDR (MEMORY_MEDPLL_STATE_ADDR + MEMORY_MEDPLL_STATE_SIZE) +#define MEMORY_CCPU_LOAD_FLAG_SIZE (4) + + +#define ACPU_CORE_BITS_ADDR (MEMORY_CCPU_LOAD_FLAG_ADDR + MEMORY_CCPU_LOAD_FLAG_SIZE) +#define ACPU_CORE_BITS_SIZE (4) + +#define ACPU_CLUSTER_IDLE_ADDR (ACPU_CORE_BITS_ADDR + ACPU_CORE_BITS_SIZE) +#define ACPU_CLUSTER_IDLE_SIZE (4) + +#define ACPU_A53_FLAGS_ADDR (ACPU_CLUSTER_IDLE_ADDR + ACPU_CLUSTER_IDLE_SIZE) +#define ACPU_A53_FLAGS_SIZE (4) + +#define ACPU_POWER_STATE_QOS_ADDR (ACPU_A53_FLAGS_ADDR+ACPU_A53_FLAGS_SIZE) +#define ACPU_POWER_STATE_QOS_SIZE (4) + +#define ACPU_UNLOCK_CORE_FLAGS_ADDR (ACPU_POWER_STATE_QOS_ADDR+ACPU_POWER_STATE_QOS_SIZE) +#define ACPU_UNLOCK_CORE_FLAGS_SIZE (8) + +#define ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR (ACPU_UNLOCK_CORE_FLAGS_ADDR + ACPU_UNLOCK_CORE_FLAGS_SIZE) +#define ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_CORE_POWERDOWN_FLAGS_ADDR (ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR + ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE) +#define ACPU_CORE_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR (ACPU_CORE_POWERDOWN_FLAGS_ADDR + ACPU_CORE_POWERDOWN_FLAGS_SIZE) +#define ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_ARM64_FLAGA (ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR + ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE) +#define ACPU_ARM64_FLAGA_SIZE (4) + +#define ACPU_ARM64_FLAGB (ACPU_ARM64_FLAGA + ACPU_ARM64_FLAGA_SIZE) +#define ACPU_ARM64_FLAGB_SIZE (4) + +#define MCU_EXCEPTION_FLAGS_ADDR (ACPU_ARM64_FLAGB + ACPU_ARM64_FLAGB_SIZE) +#define MCU_EXCEPTION_FLAGS_SIZE (4) + +#define ACPU_MASTER_CORE_STATE_ADDR (MCU_EXCEPTION_FLAGS_ADDR + MCU_EXCEPTION_FLAGS_SIZE) +#define ACPU_MASTER_CORE_STATE_SIZE (4) + +#define PWRCTRL_AXI_RESERVED_ADDR (ACPU_MASTER_CORE_STATE_ADDR + ACPU_MASTER_CORE_STATE_SIZE) + +#endif /* HISI_SRAM_MAP_H */ diff --git a/plat/hisilicon/hikey/include/plat_macros.S b/plat/hisilicon/hikey/include/plat_macros.S new file mode 100644 index 0000000..9cd276a --- /dev/null +++ b/plat/hisilicon/hikey/include/plat_macros.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <hi6220.h> +#include <platform_def.h> + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + mov_imm x16, PLAT_ARM_GICD_BASE + mov_imm x17, PLAT_ARM_GICC_BASE + + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + /* Store to the crash buf and print to cosole */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +2: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq 1f + bl asm_print_hex + adr x4, spacer + bl asm_print_str + ldr x4, [x7], #8 + bl asm_print_hex + adr x4, newline + bl asm_print_str + b 2b +1: + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI400_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE3_CLUSTER_IX)) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI400_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE4_CLUSTER_IX)) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/hisilicon/hikey/include/platform_def.h b/plat/hisilicon/hikey/include/platform_def.h new file mode 100644 index 0000000..04ea71f --- /dev/null +++ b/plat/hisilicon/hikey/include/platform_def.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <common/tbbr/tbbr_img_def.h> +#include <lib/utils_def.h> +#include <plat/common/common_def.h> + +#include <hikey_def.h> +#include <hikey_layout.h> /* BL memory region sizes, etc */ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define HIKEY_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* + * Generic platform constants + */ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x1000 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_CORE_COUNT_PER_CLUSTER) +#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL2) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + U(1)) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 +/* eMMC RPMB and eMMC User Data */ +#define MAX_IO_BLOCK_DEVICES U(2) + +/* GIC related constants (no GICR in GIC-400) */ +#define PLAT_ARM_GICD_BASE 0xF6801000 +#define PLAT_ARM_GICC_BASE 0xF6802000 +#define PLAT_ARM_GICH_BASE 0xF6804000 +#define PLAT_ARM_GICV_BASE 0xF6806000 + +/* + * Platform specific page table and MMU setup constants + */ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) +#define MAX_XLAT_TABLES 3 +#endif + +#ifdef IMAGE_BL31 +#define MAX_XLAT_TABLES 4 +#endif + +#ifdef IMAGE_BL2 +#define MAX_XLAT_TABLES 4 +#endif + +#define MAX_MMAP_REGIONS 16 + +/* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + */ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk new file mode 100644 index 0000000..807a915 --- /dev/null +++ b/plat/hisilicon/hikey/platform.mk @@ -0,0 +1,172 @@ +# +# Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Non-TF Boot ROM +RESET_TO_BL2 := 1 + +# On Hikey, the TSP can execute from TZC secure area in DRAM (default) +# or SRAM. +HIKEY_TSP_RAM_LOCATION ?= dram +ifeq (${HIKEY_TSP_RAM_LOCATION}, dram) + HIKEY_TSP_RAM_LOCATION_ID = HIKEY_DRAM_ID +else ifeq (${HIKEY_TSP_RAM_LOCATION}, sram) + HIKEY_TSP_RAM_LOCATION_ID = HIKEY_SRAM_ID +else + $(error "Currently unsupported HIKEY_TSP_RAM_LOCATION value") +endif + +CONSOLE_BASE := PL011_UART3_BASE +CRASH_CONSOLE_BASE := PL011_UART3_BASE +PLAT_PARTITION_MAX_ENTRIES := 12 +PLAT_PL061_MAX_GPIOS := 160 +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 +ENABLE_SVE_FOR_NS := 0 + +# Process flags +$(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID)) +$(eval $(call add_define,CONSOLE_BASE)) +$(eval $(call add_define,CRASH_CONSOLE_BASE)) +$(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) +$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +USE_COHERENT_MEM := 1 + +PLAT_INCLUDES := -Iplat/hisilicon/hikey/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/hisilicon/hikey/aarch64/hikey_common.c + +BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl1_setup.c \ + plat/hisilicon/hikey/hikey_bl_common.c \ + plat/hisilicon/hikey/hikey_io_storage.c + +BL2_SOURCES += common/desc_image_load.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/mmc/mmc.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/synopsys/emmc/dw_mmc.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c \ + plat/hisilicon/hikey/hikey_bl2_setup.c \ + plat/hisilicon/hikey/hikey_bl_common.c \ + plat/hisilicon/hikey/hikey_security.c \ + plat/hisilicon/hikey/hikey_ddr.c \ + plat/hisilicon/hikey/hikey_image_load.c \ + plat/hisilicon/hikey/hikey_io_storage.c \ + plat/hisilicon/hikey/hisi_dvfs.c \ + plat/hisilicon/hikey/hisi_mcu.c + +ifeq (${SPD},opteed) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +include lib/zlib/zlib.mk +PLAT_INCLUDES += -Ilib/zlib +BL2_SOURCES += $(ZLIB_SOURCES) + +HIKEY_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL31_SOURCES += drivers/arm/cci/cci.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl31_setup.c \ + plat/hisilicon/hikey/hikey_pm.c \ + plat/hisilicon/hikey/hikey_topology.c \ + plat/hisilicon/hikey/hisi_ipc.c \ + plat/hisilicon/hikey/hisi_pwrc.c \ + plat/hisilicon/hikey/hisi_pwrc_sram.S \ + ${HIKEY_GIC_SOURCES} +ifeq (${ENABLE_PMF}, 1) +BL31_SOURCES += plat/hisilicon/hikey/hisi_sip_svc.c \ + lib/pmf/pmf_smc.c +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + +BL1_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey/hikey_tbbr.c \ + plat/hisilicon/hikey/hikey_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey/hikey_tbbr.c \ + plat/hisilicon/hikey/hikey_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(BUILD_PLAT)/bl1/hikey_rotpk.o: $(ROTPK_HASH) +$(BUILD_PLAT)/bl2/hikey_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +# Enable workarounds for selected Cortex-A53 errata. +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +FIP_ALIGN := 512 diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/plat/hisilicon/hikey960/aarch64/hikey960_common.c new file mode 100644 index 0000000..c70286f --- /dev/null +++ b/plat/hisilicon/hikey960/aarch64/hikey960_common.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <plat/common/platform.h> + +#include "../hikey960_def.h" +#include "../hikey960_private.h" + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE - DDR_SEC_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_BL1_RW MAP_REGION_FLAT(BL1_RW_BASE, \ + BL1_RW_LIMIT - BL1_RW_BASE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_UFS_DATA MAP_REGION_FLAT(HIKEY960_UFS_DATA_BASE, \ + HIKEY960_UFS_DATA_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_UFS_DESC MAP_REGION_FLAT(HIKEY960_UFS_DESC_BASE, \ + HIKEY960_UFS_DESC_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * hikey960_init_mmu_elx() will give the available subset of that, + */ +#ifdef IMAGE_BL1 +static const mmap_region_t hikey960_mmap[] = { + MAP_UFS_DATA, + MAP_BL1_RW, + MAP_UFS_DESC, + MAP_DEVICE, + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t hikey960_mmap[] = { + MAP_DDR, + MAP_DEVICE, + MAP_TSP_MEM, + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t hikey960_mmap[] = { + MAP_DEVICE, + {0} +}; +#endif + +#ifdef IMAGE_BL32 +static const mmap_region_t hikey960_mmap[] = { + MAP_DEVICE, + MAP_DDR, + {0} +}; +#endif + +/* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + */ +#define HIKEY960_CONFIGURE_MMU_EL(_el) \ + void hikey960_init_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(hikey960_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +HIKEY960_CONFIGURE_MMU_EL(1) +HIKEY960_CONFIGURE_MMU_EL(3) + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return NS_BL1U_BASE; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return 1920000; +} diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S new file mode 100644 index 0000000..5381369 --- /dev/null +++ b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <cortex_a53.h> +#include <cortex_a73.h> +#include "../hikey960_def.h" + + .globl plat_my_core_pos + .globl platform_mem_init + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_report_exception + .globl plat_reset_handler + .globl clr_ex + .globl nop + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on HIKEY. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, CRASH_CONSOLE_BASE + mov_imm x1, PL011_UART_CLK_IN_HZ + mov_imm x2, PL011_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, CRASH_CONSOLE_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On HIKEY platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mov x8, x30 + + /* Turn on LED according to x0 (0 -- f) */ + ldr x2, =0xf7020000 + and x1, x0, #1 + str w1, [x2, #4] + and x1, x0, #2 + str w1, [x2, #8] + and x1, x0, #4 + str w1, [x2, #16] + and x1, x0, #8 + str w1, [x2, #32] + + mrs x2, currentel + and x2, x2, #0x0c + /* Check EL1 */ + cmp x2, #0x04 + beq plat_report_el1 + + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el3_str + bl asm_print_str + + mrs x4, esr_el3 + bl asm_print_hex + + adr x4, elr_el3_str + bl asm_print_str + + mrs x4, elr_el3 + bl asm_print_hex + b plat_report_end + +plat_report_el1: + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el1_str + bl asm_print_str + + mrs x4, esr_el1 + bl asm_print_hex + + adr x4, elr_el1_str + bl asm_print_str + + mrs x4, elr_el1 + bl asm_print_hex +plat_report_end: + mov x30, x8 + ret +endfunc plat_report_exception + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * void clrex(void); + * ----------------------------------------------------- + */ +func clr_ex + clrex + ret +endfunc clr_ex + + /* ----------------------------------------------------- + * void nop(void); + * ----------------------------------------------------- + */ +func nop + nop + ret +endfunc nop + +.section .rodata.rev_err_str, "aS" +plat_err_str: + .asciz "\nPlatform exception reporting:" +esr_el3_str: + .asciz "\nESR_EL3: " +elr_el3_str: + .asciz "\nELR_EL3: " +esr_el1_str: + .asciz "\nESR_EL1: " +elr_el1_str: + .asciz "\nELR_EL1: " diff --git a/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c new file mode 100644 index 0000000..a6a4949 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <hi3660.h> +#include <hisi_ipc.h> +#include "../../hikey960_private.h" + +#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6)) +#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04) +#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08) +#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C) +#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10) +#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14) +#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18) +#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C) +#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \ + ((d) * 4)) +#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3)) +#define IPC_LOCK_REG (IPC_BASE + 0xA00) +#define IPC_ACK_BIT_SHIFT (1 << 7) +#define IPC_UNLOCK_VALUE (0x1ACCE551) + +/********************************************************* + *bit[31:24]:0~AP + *bit[23:16]:0x1~A15, 0x2~A7 + *bit[15:8]:0~ON, 1~OFF + *bit[7:0]:0x3 cpu power mode + *********************************************************/ +#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \ + ((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode)) + +/********************************************************* + *bit[15:8]:0~no idle, 1~idle + *bit[7:0]:cpux + *********************************************************/ + +#define IPC_CMD_PARA(is_idle, cpu) \ + ((is_idle << 8) | (cpu)) + +#define IPC_STATE_IDLE 0x10 + +enum src_id { + SRC_IDLE = 0, + SRC_A15 = 1 << 0, + SRC_A7 = 1 << 1, + SRC_IOM3 = 1 << 2, + SRC_LPM3 = 1 << 3 +}; + +/*lpm3's mailboxs are 13~17*/ +enum lpm3_mbox_id { + LPM3_MBX0 = 13, + LPM3_MBX1, + LPM3_MBX2, + LPM3_MBX3, + LPM3_MBX4, +}; + +static void cpu_relax(void) +{ + volatile int i; + + for (i = 0; i < 10; i++) + nop(); +} + +static inline void +hisi_ipc_clear_ack(enum src_id source, enum lpm3_mbox_id mbox) +{ + unsigned int int_status = 0; + + do { + int_status = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + int_status &= 0xF0; + cpu_relax(); + } while (int_status != IPC_ACK_BIT_SHIFT); + + mmio_write_32(IPC_MBX_ICLR_REG(mbox), source); +} + +static void +hisi_ipc_send_cmd_with_ack(enum src_id source, enum lpm3_mbox_id mbox, + unsigned int cmdtype, unsigned int cmdpara) +{ + unsigned int regval; + unsigned int mask; + unsigned int state; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + /* wait for idle and occupy */ + do { + state = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + if (state == IPC_STATE_IDLE) { + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); + regval = mmio_read_32(IPC_MBX_SOURCE_REG(mbox)); + if (regval == source) + break; + } + cpu_relax(); + + } while (1); + + /* auto answer */ + mmio_write_32(IPC_MBX_MODE_REG(mbox), 0x1); + + mask = (~((int)source | SRC_LPM3) & 0x3F); + /* mask the other cpus */ + mmio_write_32(IPC_MBX_IMASK_REG(mbox), mask); + /* set data */ + mmio_write_32(IPC_MBX_DATA_REG(mbox, 0), cmdtype); + mmio_write_32(IPC_MBX_DATA_REG(mbox, 1), cmdpara); + /* send cmd */ + mmio_write_32(IPC_MBX_SEND_REG(mbox), source); + /* wait ack and clear */ + hisi_ipc_clear_ack(source, mbox); + + /* release mailbox */ + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); +} + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, cluster, mode, 0x3); + cmdpara = IPC_CMD_PARA(0, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + if (affinity_level == 0x3) + cmdtype = IPC_CMD_TYPE(0, -1, 0x1, 0x3 + affinity_level); + else + cmdtype = IPC_CMD_TYPE(0, cluster, 0x1, 0x3 + affinity_level); + + cmdpara = IPC_CMD_PARA(1, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x1, 0x0); + cmdpara = IPC_CMD_PARA(0, 0); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x0, 0x0); + cmdpara = cmd_id; + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +int hisi_ipc_init(void) +{ + int ret = 0; + enum lpm3_mbox_id i = LPM3_MBX0; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + for (i = LPM3_MBX0; i <= LPM3_MBX4; i++) { + mmio_write_32(IPC_MBX_MODE_REG(i), 1); + mmio_write_32(IPC_MBX_IMASK_REG(i), + ((int)SRC_IOM3 | (int)SRC_A15 | (int)SRC_A7)); + mmio_write_32(IPC_MBX_ICLR_REG(i), SRC_A7); + } + + return ret; +} diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c new file mode 100644 index 0000000..91d8033 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <../hikey960_def.h> +#include <hisi_ipc.h> +#include "hisi_pwrc.h" + + +/* resource lock api */ +#define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE)) +#define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE)) +#define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE)) + +#define LOCK_BIT (0x1 << 28) +#define LOCK_ID_MASK (0x7u << 29) +#define CPUIDLE_LOCK_ID(core) (0x6 - (core)) +#define LOCK_UNLOCK_OFFSET 0x4 +#define LOCK_STAT_OFFSET 0x8 + +#define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16) +#define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20) + +/* cpu hotplug flag api */ +#define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR) +#define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE)) + +#define CPUIDLE_FLAG_REG(cluster) \ + ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \ + REG_SCBAKDATA9_OFFSET) +#define CLUSTER_IDLE_BIT BIT(8) +#define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F) + +#define AP_SUSPEND_FLAG (1 << 16) + +#define CLUSTER_PWDN_IDLE (0<<28) +#define CLUSTER_PWDN_HOTPLUG (1<<28) +#define CLUSTER_PWDN_SR (2<<28) + +#define CLUSTER0_PDC_OFFSET 0x260 +#define CLUSTER1_PDC_OFFSET 0x300 + +#define PDC_EN_OFFSET 0x0 +#define PDC_COREPWRINTEN_OFFSET 0x4 +#define PDC_COREPWRINTSTAT_OFFSET 0x8 +#define PDC_COREGICMASK_OFFSET 0xc +#define PDC_COREPOWERUP_OFFSET 0x10 +#define PDC_COREPOWERDN_OFFSET 0x14 +#define PDC_COREPOWERSTAT_OFFSET 0x18 + +#define PDC_COREPWRSTAT_MASK (0XFFFF) + +enum pdc_gic_mask { + PDC_MASK_GIC_WAKE_IRQ, + PDC_UNMASK_GIC_WAKE_IRQ +}; + +enum pdc_finish_int_mask { + PDC_DISABLE_FINISH_INT, + PDC_ENABLE_FINISH_INT +}; + +static void hisi_resource_lock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_id = (lockid << 29); + unsigned int lock_val = lock_id | LOCK_BIT; + unsigned int lock_state; + + do { + mmio_write_32(offset, lock_val); + lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset); + } while ((lock_state & LOCK_ID_MASK) != lock_id); +} + +static void hisi_resource_unlock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_val = (lockid << 29) | LOCK_BIT; + + mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val); +} + + +static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_lock(lock_id, RES2_LOCK_BASE); +} + +static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_unlock(lock_id, RES2_LOCK_BASE); +} + +/* get the resource lock */ +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset); +} + +/* release the resource lock */ +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset); +} + +unsigned int hisi_get_cpuidle_flag(unsigned int cluster) +{ + unsigned int val; + + val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); + val &= 0xF; + + return val; +} + +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); +} + +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); + +} + +int hisi_test_ap_suspend_flag(void) +{ + unsigned int val1; + unsigned int val2; + + val1 = mmio_read_32(CPUIDLE_FLAG_REG(0)); + val1 &= AP_SUSPEND_FLAG; + + val2 = mmio_read_32(CPUIDLE_FLAG_REG(1)); + val2 &= AP_SUSPEND_FLAG; + + val1 |= val2; + return (val1 != 0); +} + +void hisi_set_cluster_pwdn_flag(unsigned int cluster, + unsigned int core, unsigned int value) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val &= ~(0x3U << ((2 * cluster) + 28)); + val |= (value << (2 * cluster)); + mmio_write_32(REG_SCBAKDATA3_OFFSET, val); + + hisi_cpuhotplug_unlock(cluster, core); +} + +unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + return val; +} + +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + if (val) + return 0; + else + return 1; +} + +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +int cluster_is_powered_on(unsigned int cluster) +{ + unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + int ret; + + if (cluster == 0) + ret = val & CLUSTER0_CPUS_ONLINE_MASK; + else + ret = val & CLUSTER1_CPUS_ONLINE_MASK; + + return !!ret; +} + +static void *hisi_get_pdc_addr(unsigned int cluster) +{ + void *pdc_base_addr; + uintptr_t addr; + + if (cluster == 0) + addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE); + else + addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE); + pdc_base_addr = (void *)addr; + + return pdc_base_addr; +} + +static unsigned int hisi_get_pdc_stat(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET); + + return val; +} + +static int check_hotplug(unsigned int cluster, unsigned int boot_flag) +{ + unsigned int mask = 0xF; + + if (hisi_test_ap_suspend_flag() || + ((boot_flag & mask) == mask)) + return 0; + + return 1; +} + +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) +{ + unsigned int mask = 0xf << (core * 4); + unsigned int pdc_stat = hisi_get_pdc_stat(cluster); + unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core); + unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster); + + mask = (PDC_COREPWRSTAT_MASK & (~mask)); + pdc_stat &= mask; + + if ((boot_flag ^ cpuidle_flag) || pdc_stat || + check_hotplug(cluster, boot_flag)) + return 0; + else + return 1; +} + +void hisi_disable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x0); +} + +void hisi_enable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x1); +} + +void hisi_pdc_set_intmask(void *pdc_base_addr, + unsigned int core, + enum pdc_finish_int_mask intmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET); + if (intmask == PDC_ENABLE_FINISH_INT) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val); +} + +static inline void hisi_pdc_set_gicmask(void *pdc_base_addr, + unsigned int core, + enum pdc_gic_mask gicmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET); + if (gicmask == PDC_MASK_GIC_WAKE_IRQ) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val); +} + +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster) +{ + int i; + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + for (i = 0; i < 4; i++) + hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ); +} + +static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET, + BIT(core)); +} + +static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_powerup_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerdn_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerup_cluster(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_on_off(core, cluster, PM_ON); +} + +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_core_idle(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_suspend(core, cluster, 0x3); +} diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h new file mode 100644 index 0000000..e0cb381 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_PWRC_H +#define HISI_PWRC_H + +#include <hi3660.h> +#include <hi3660_crg.h> + +#define PCTRL_BASE (PCTRL_REG_BASE) +#define CRG_BASE (CRG_REG_BASE) + +#define SOC_CRGPERIPH_A53_PDCEN_ADDR(base) ((base) + (0x260)) +#define SOC_CRGPERIPH_MAIA_PDCEN_ADDR(base) ((base) + (0x300)) + +#define SOC_PCTRL_RESOURCE0_LOCK_ADDR(base) ((base) + (0x400)) +#define SOC_PCTRL_RESOURCE0_UNLOCK_ADDR(base) ((base) + (0x404)) +#define SOC_PCTRL_RESOURCE0_LOCK_ST_ADDR(base) ((base) + (0x408)) +#define SOC_PCTRL_RESOURCE1_LOCK_ADDR(base) ((base) + (0x40C)) +#define SOC_PCTRL_RESOURCE1_UNLOCK_ADDR(base) ((base) + (0x410)) +#define SOC_PCTRL_RESOURCE1_LOCK_ST_ADDR(base) ((base) + (0x414)) +#define SOC_PCTRL_RESOURCE2_LOCK_ADDR(base) ((base) + (0x418)) + +#define SOC_SCTRL_SCBAKDATA3_ADDR(base) ((base) + (0x418)) +#define SOC_SCTRL_SCBAKDATA8_ADDR(base) ((base) + (0x42C)) +#define SOC_SCTRL_SCBAKDATA9_ADDR(base) ((base) + (0x430)) + +#define SOC_ACPU_SCTRL_BASE_ADDR (0xFFF0A000) + +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core); +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core); +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core); +int cluster_is_powered_on(unsigned int cluster); +void hisi_enter_core_idle(unsigned int cluster, unsigned int core); +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core); +int hisi_test_ap_suspend_flag(void); +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core); + + +/* pdc api */ +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster); +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core); +void hisi_disable_pdc(unsigned int cluster); +void hisi_enable_pdc(unsigned int cluster); +void hisi_powerup_core(unsigned int cluster, unsigned int core); +void hisi_powerdn_core(unsigned int cluster, unsigned int core); +void hisi_powerup_cluster(unsigned int cluster, unsigned int core); +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core); +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core); + +#endif /* HISI_PWRC_H */ diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c new file mode 100644 index 0000000..0a2d062 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <bl1/tbbr/tbbr_img_desc.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/interrupt_props.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/pl011.h> +#include <drivers/delay_timer.h> +#include <drivers/dw_ufs.h> +#include <drivers/generic_delay_timer.h> +#include <drivers/ufs.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <hi3660.h> +#include "hikey960_def.h" +#include "hikey960_private.h" + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/* + * Declarations of linker defined symbols which will help us find the layout + * of trusted RAM + */ + +/* Data structure which holds the extents of the trusted RAM for BL1 */ +static meminfo_t bl1_tzram_layout; +static console_t console; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +const gicv2_driver_data_t hikey960_gic_data = { + .gicd_base = GICD_REG_BASE, + .gicc_base = GICC_REG_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/* + * Perform any BL1 specific platform actions. + */ +void bl1_early_platform_setup(void) +{ + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + /* Initialize the console to provide early debug support */ + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL1_RW_BASE; + bl1_tzram_layout.total_size = BL1_RW_SIZE; + + INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ +} + +/* + * Perform the very early platform specific architecture setup here. At the + * moment this only does basic initialization. Later architectural setup + * (bl1_arch_setup()) does not do anything platform specific. + */ +void bl1_plat_arch_setup(void) +{ + hikey960_init_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL1_RO_BASE, + BL1_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +static void hikey960_ufs_reset(void) +{ + unsigned int data, mask; + + mmio_write_32(CRG_PERDIS7_REG, 1 << 14); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + do { + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + } while (data & BIT_SYSCTRL_REF_CLOCK_EN); + /* use abb clk */ + mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); + mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); + mdelay(1); + mmio_write_32(CRG_PEREN7_REG, 1 << 14); + mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + + mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while ((data & PERI_UFS_BIT) == 0); + mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); + mdelay(1); + mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET); + /* clear SC_DIV_UFS_PERIBUS */ + mask = SC_DIV_UFS_PERIBUS << 16; + mmio_write_32(CRG_CLKDIV17_REG, mask); + /* set SC_DIV_UFSPHY_CFG(3) */ + mask = SC_DIV_UFSPHY_CFG_MASK << 16; + data = SC_DIV_UFSPHY_CFG(3); + mmio_write_32(CRG_CLKDIV16_REG, mask | data); + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; + data |= 0x39; + mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); + mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, + MASK_UFS_CLK_GATE_BYPASS); + mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); + + mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); + mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); + mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); + mdelay(1); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); + mdelay(20); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + 0x03300330); + + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while (data & PERI_UFS_BIT); +} + +static void hikey960_ufs_init(void) +{ + dw_ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params)); + ufs_params.reg_base = UFS_REG_BASE; + ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; + ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; + + if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) + hikey960_ufs_reset(); + dw_ufs_init(&ufs_params); +} + +/* + * Function which will perform any remaining platform-specific setup that can + * occur after the MMU and data cache have been enabled. + */ +void bl1_platform_setup(void) +{ + hikey960_clk_init(); + hikey960_pmu_init(); + hikey960_regulator_enable(); + hikey960_tzc_init(); + hikey960_peri_init(); + hikey960_ufs_init(); + hikey960_pinmux_init(); + hikey960_gpio_init(); + hikey960_io_setup(); +} + +/* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or not. + */ +unsigned int bl1_plat_get_next_image_id(void) +{ + unsigned int mode, ret; + + mode = mmio_read_32(SCTRL_BAK_DATA0_REG); + switch (mode & BOOT_MODE_MASK) { + case BOOT_MODE_RECOVERY: + ret = NS_BL1U_IMAGE_ID; + break; + default: + WARN("Invalid boot mode is found:%d\n", mode); + panic(); + } + return ret; +} + +image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +{ + unsigned int index = 0; + + while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { + if (bl1_tbbr_image_descs[index].image_id == image_id) + return &bl1_tbbr_image_descs[index]; + index++; + } + + return NULL; +} + +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + unsigned int data = 0; + uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; + + if (image_id != NS_BL1U_IMAGE_ID) + panic(); + /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ + memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, + NS_BL1U_SIZE); + memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); + inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey960_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + /* CNTFRQ is read-only in EL1 */ + write_cntfrq_el0(plat_get_syscnt_freq2()); + data = read_cpacr_el1(); + do { + data |= 3 << 20; + write_cpacr_el1(data); + data = read_cpacr_el1(); + } while ((data & (3 << 20)) != (3 << 20)); + INFO("cpacr_el1:0x%x\n", data); + + ep_info->args.arg0 = 0xffff & read_mpidr(); + ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} diff --git a/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c b/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c new file mode 100644 index 0000000..e42785a --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + +#else /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = HIKEY960_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager + * image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged + * image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = HIKEY960_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + +#ifdef SPD_spmd + /* Fill TOS_FW_CONFIG related information */ + { + .image_id = TOS_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = DDR_SEC_CONFIG_BASE, + .image_info.image_max_size = DDR_SEC_CONFIG_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif + +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = NS_BL1U_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = NS_BL1U_BASE, + .image_info.image_max_size = 0x200000 /* 2MB */, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c new file mode 100644 index 0000000..7334853 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/arm/pl011.h> +#include <drivers/delay_timer.h> +#include <drivers/dw_ufs.h> +#include <drivers/generic_delay_timer.h> +#include <drivers/partition/partition.h> +#include <drivers/ufs.h> +#include <lib/mmio.h> +#ifdef SPD_opteed +#include <lib/optee_utils.h> +#endif + +#include <hi3660.h> +#include "hikey960_def.h" +#include "hikey960_private.h" + +#define BL2_RW_BASE (BL_CODE_END) + +/* BL2 platform parameters passed to BL31 */ +static plat_params_from_bl2_t plat_params_from_bl2; + +static meminfo_t bl2_el3_tzram_layout; +static console_t console; +extern int load_lpm3(void); + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_hikey960_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int i; + int *buf; + + assert(scp_bl2_image_info->image_size < SCP_BL2_SIZE); + + INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); + + INFO("BL2: SCP_BL2: 0x%lx@0x%x\n", + scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + buf = (int *)scp_bl2_image_info->image_base; + + INFO("BL2: SCP_BL2 HEAD:\n"); + for (i = 0; i < 64; i += 4) + INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3]); + + buf = (int *)(scp_bl2_image_info->image_base + + scp_bl2_image_info->image_size - 256); + + INFO("BL2: SCP_BL2 TAIL:\n"); + for (i = 0; i < 64; i += 4) + INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3]); + + INFO("BL2: SCP_BL2 transferred to SCP\n"); + + load_lpm3(); + (void)buf; + + return 0; +} + +static void hikey960_ufs_reset(void) +{ + unsigned int data, mask; + + mmio_write_32(CRG_PERDIS7_REG, 1 << 14); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + do { + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + } while (data & BIT_SYSCTRL_REF_CLOCK_EN); + /* use abb clk */ + mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); + mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); + mdelay(1); + mmio_write_32(CRG_PEREN7_REG, 1 << 14); + mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + + mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while ((data & PERI_UFS_BIT) == 0); + mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); + mdelay(1); + mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET); + /* clear SC_DIV_UFS_PERIBUS */ + mask = SC_DIV_UFS_PERIBUS << 16; + mmio_write_32(CRG_CLKDIV17_REG, mask); + /* set SC_DIV_UFSPHY_CFG(3) */ + mask = SC_DIV_UFSPHY_CFG_MASK << 16; + data = SC_DIV_UFSPHY_CFG(3); + mmio_write_32(CRG_CLKDIV16_REG, mask | data); + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; + data |= 0x39; + mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); + mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, + MASK_UFS_CLK_GATE_BYPASS); + mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); + + mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); + mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); + mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); + mdelay(1); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); + mdelay(20); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + 0x03300330); + + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while (data & PERI_UFS_BIT); +} + +static void hikey960_init_ufs(void) +{ + dw_ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params_t)); + ufs_params.reg_base = UFS_REG_BASE; + ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; + ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; + hikey960_ufs_reset(); + dw_ufs_init(&ufs_params); +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t hikey960_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t hikey960_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +uint32_t hikey960_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +int hikey960_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + assert(bl_mem_params); + + switch (image_id) { + case BL31_IMAGE_ID: + /* Pass BL2 platform parameter to BL31 */ + bl_mem_params->ep_info.args.arg1 = (uint64_t) &plat_params_from_bl2; + break; + +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } +#endif + bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_hikey960_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + return hikey960_set_fip_addr(image_id, "fip"); +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return hikey960_bl2_handle_post_image_load(image_id); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + /* Initialize the console to provide early debug support */ + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + /* + * Allow BL2 to see the whole Trusted RAM. + */ + bl2_el3_tzram_layout.total_base = BL2_RW_BASE; + bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE; +} + +void bl2_el3_plat_arch_setup(void) +{ + hikey960_init_mmu_el3(bl2_el3_tzram_layout.total_base, + bl2_el3_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl2_platform_setup(void) +{ + int ret; + + /* disable WDT0 */ + if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) { + mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK); + mmio_write_32(WDT0_REG_BASE + WDT_CONTROL_OFFSET, 0); + mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, 0); + } + hikey960_clk_init(); + hikey960_pmu_init(); + hikey960_regulator_enable(); + hikey960_tzc_init(); + hikey960_peri_init(); + hikey960_pinmux_init(); + hikey960_gpio_init(); + hikey960_init_ufs(); + hikey960_io_setup(); + + /* Read serial number from storage */ + plat_params_from_bl2.fastboot_serno = 0; + ret = hikey960_load_serialno(&plat_params_from_bl2.fastboot_serno); + if (ret != 0) { + ERROR("BL2: could not read serial number\n"); + } + INFO("BL2: fastboot_serno %lx\n", plat_params_from_bl2.fastboot_serno); + flush_dcache_range((uintptr_t)&plat_params_from_bl2, sizeof(plat_params_from_bl2_t)); +} diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c new file mode 100644 index 0000000..159eee9 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <bl31/interrupt_mgmt.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/interrupt_props.h> +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/pl011.h> +#include <drivers/console.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <plat/common/platform.h> +#include <services/el3_spmc_ffa_memory.h> + +#include <hi3660.h> +#include <hisi_ipc.h> +#include "hikey960_def.h" +#include "hikey960_private.h" + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; +static console_t console; + +/* fastboot serial number consumed by Kinibi SPD/LP for gpd.tee.deviceID. */ +uint64_t fastboot_serno; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +const gicv2_driver_data_t hikey960_gic_data = { + .gicd_base = GICD_REG_BASE, + .gicc_base = GICC_REG_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +static const int cci_map[] = { + CCI400_SL_IFACE3_CLUSTER_IX, + CCI400_SL_IFACE4_CLUSTER_IX +}; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + unsigned int id, uart_base; + void *from_bl2; + plat_params_from_bl2_t *plat_params_from_bl2 = (plat_params_from_bl2_t *) arg1; + + from_bl2 = (void *) arg0; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + + /* Initialize the console to provide early debug support */ + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Initialize CCI driver */ + cci_init(CCI400_REG_BASE, cci_map, ARRAY_SIZE(cci_map)); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + /* Fastboot serial number passed from BL2 as a platform parameter */ + fastboot_serno = plat_params_from_bl2->fastboot_serno; + INFO("BL31: fastboot_serno %lx\n", fastboot_serno); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_ep_info.pc == 0) + panic(); +} + +void bl31_plat_arch_setup(void) +{ +#if SPMC_AT_EL3 + mmap_add_region(DDR2_SEC_BASE, DDR2_SEC_BASE, DDR2_SEC_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); +#endif + + hikey960_init_mmu_el3(BL31_BASE, + BL31_LIMIT - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +static void hikey960_edma_init(void) +{ + int i; + uint32_t non_secure; + + non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC; + mmio_write_32(EDMAC_SEC_CTRL, non_secure); + + /* Channel 0 is reserved for LPM3, keep secure */ + for (i = 1; i < EDMAC_CHANNEL_NUMS; i++) { + mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18)); + } +} + +static void hikey960_iomcu_dma_init(void) +{ + int i; + uint32_t non_secure; + + non_secure = IOMCU_DMAC_SEC_CTRL_INTR_SEC | IOMCU_DMAC_SEC_CTRL_GLOBAL_SEC; + mmio_write_32(IOMCU_DMAC_SEC_CTRL, non_secure); + + /* channels 0-3 are reserved */ + for (i = 4; i < IOMCU_DMAC_CHANNEL_NUMS; i++) { + mmio_write_32(IOMCU_DMAC_AXI_CONF(i), IOMCU_DMAC_AXI_CONF_ARPROT_NS | + IOMCU_DMAC_AXI_CONF_AWPROT_NS); + } +} + +#if SPMC_AT_EL3 +/* + * On the hikey960 platform when using the EL3 SPMC implementation allocate the + * datastore for tracking shared memory descriptors in the RAM2 DRAM section + * to ensure sufficient storage can be allocated. + * Provide an implementation of the accessor method to allow the datastore + * details to be retrieved by the SPMC. + * The SPMC will take care of initializing the memory region. + */ + +#define SPMC_SHARED_MEMORY_OBJ_SIZE (512 * 1024) + +__section(".ram2_region") uint8_t plat_spmc_shmem_datastore[SPMC_SHARED_MEMORY_OBJ_SIZE]; + +int plat_spmc_shmem_datastore_get(uint8_t **datastore, size_t *size) +{ + *datastore = plat_spmc_shmem_datastore; + *size = SPMC_SHARED_MEMORY_OBJ_SIZE; + return 0; +} + +/* + * Add dummy implementations of memory management related platform hooks. + * These can be used to implement platform specific functionality to support + * a memory sharing/lending operation. + * + * Note: The hooks must be located as part of the initial share request and + * final reclaim to prevent order dependencies with operations that may take + * place in the normal world without visibility of the SPMC. + */ +int plat_spmc_shmem_begin(struct ffa_mtd *desc) +{ + return 0; +} + +int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) +{ + return 0; +} + +#endif + +void bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey960_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + hikey960_edma_init(); + hikey960_iomcu_dma_init(); + hikey960_gpio_init(); + + hisi_ipc_init(); +} + +#ifdef SPD_none +static uint64_t hikey_debug_fiq_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + int intr, intr_raw; + + /* Acknowledge interrupt */ + intr_raw = plat_ic_acknowledge_interrupt(); + intr = plat_ic_get_interrupt_id(intr_raw); + ERROR("Invalid interrupt: intr=%d\n", intr); + console_flush(); + panic(); + + return 0; +} +#elif defined(SPD_spmd) && (SPMC_AT_EL3 == 0) +/* + * A dummy implementation of the platform handler for Group0 secure interrupt. + */ +int plat_spmd_handle_group0_interrupt(uint32_t intid) +{ + (void)intid; + return -1; +} +#endif + +void bl31_plat_runtime_setup(void) +{ +#ifdef SPD_none + uint32_t flags; + int32_t rc; + + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + hikey_debug_fiq_handler, + flags); + if (rc != 0) + panic(); +#endif +} diff --git a/plat/hisilicon/hikey960/hikey960_bl_common.c b/plat/hisilicon/hikey960/hikey960_bl_common.c new file mode 100644 index 0000000..3c4a164 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl_common.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/pl061_gpio.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#include <hi3660.h> +#include "hikey960_private.h" + +void hikey960_clk_init(void) +{ + /* change ldi0 sel to ppll2 */ + mmio_write_32(0xfff350b4, 0xf0002000); + /* ldi0 20' */ + mmio_write_32(0xfff350bc, 0xfc004c00); +} + +void hikey960_pmu_init(void) +{ + /* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */ + mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG); +} + +static void hikey960_enable_ppll3(void) +{ + /* enable ppll3 */ + mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305); + mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000); + mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000); +} + +static void bus_idle_clear(unsigned int value) +{ + unsigned int pmc_value, value1, value2; + int timeout = 100; + + pmc_value = value << 16; + pmc_value &= ~value; + mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value); + + for (;;) { + value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG); + value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG); + if (((value1 & value) == 0) && ((value2 & value) == 0)) + break; + udelay(1); + timeout--; + if (timeout <= 0) { + WARN("%s timeout\n", __func__); + break; + } + } +} + +static void set_vivobus_power_up(void) +{ + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x00020002); + mmio_write_32(CRG_PEREN0_REG, 0x00001000); +} + +static void set_dss_power_up(void) +{ + /* set edc0 133MHz = 1600MHz / 12 */ + mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b); + /* set ldi0 ppl0 */ + mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000); + /* set ldi0 133MHz, 1600MHz / 12 */ + mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000020); + udelay(100); + /* DISP CRG */ + mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); + mmio_write_32(CRG_PEREN0_REG, 0x00002000); + mmio_write_32(CRG_PEREN3_REG, 0x0003b000); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x0003b000); + mmio_write_32(CRG_PERDIS0_REG, 0x00002000); + mmio_write_32(CRG_CLKDIV18_REG, 0x01400000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000040); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006); + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); + mmio_write_32(CRG_PEREN0_REG, 0x00002000); + mmio_write_32(CRG_PEREN3_REG, 0x0003b000); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS); + /* set edc0 400MHz for 2K 1600MHz / 4 */ + mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003); + /* set ldi 266MHz, 1600MHz / 6 */ + mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400); +} + +static void set_vcodec_power_up(void) +{ + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x00040004); + mmio_write_32(CRG_PEREN0_REG, 0x00000060); + mmio_write_32(CRG_PEREN2_REG, 0x10000000); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC); +} + +static void set_vdec_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000004); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); + mmio_write_32(CRG_PEREN2_REG, 0x20080000); + mmio_write_32(CRG_PEREN3_REG, 0x00000800); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x00000800); + mmio_write_32(CRG_PERDIS2_REG, 0x20080000); + mmio_write_32(CRG_CLKDIV18_REG, 0x80000000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000004); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); + mmio_write_32(CRG_PEREN2_REG, 0x20080000); + mmio_write_32(CRG_PEREN3_REG, 0x00000800); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC); +} + +static void set_venc_power_up(void) +{ + /* set venc ppll3 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x18001000); + /* set venc 258MHz, 1290MHz / 5 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000002); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); + mmio_write_32(CRG_PEREN2_REG, 0x40000100); + mmio_write_32(CRG_PEREN3_REG, 0x00000400); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x00000400); + mmio_write_32(CRG_PERDIS2_REG, 0x40000100); + mmio_write_32(CRG_CLKDIV19_REG, 0x00010000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000002); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); + mmio_write_32(CRG_PEREN2_REG, 0x40000100); + mmio_write_32(CRG_PEREN3_REG, 0x00000400); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC); + /* set venc 645MHz, 1290MHz / 2 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040); +} + +static void set_isp_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000001); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); + mmio_write_32(CRG_PEREN5_REG, 0x01000010); + mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS5_REG, 0x01000010); + mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000); + mmio_write_32(CRG_CLKDIV18_REG, 0x70000000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000001); + /* unreset */ + mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); + mmio_write_32(CRG_PEREN5_REG, 0x01000010); + mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP); + /* csi clk enable */ + mmio_write_32(CRG_PEREN3_REG, 0x00700000); +} + +static void set_ivp_power_up(void) +{ + /* set ivp ppll0 */ + mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000); + /* set ivp 267MHz, 1600MHz / 6 */ + mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00200000); + udelay(100); + /* IVP CRG unreset */ + mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001); + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); + mmio_write_32(CRG_PEREN4_REG, 0x000000a8); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS4_REG, 0x000000a8); + mmio_write_32(CRG_CLKDIV20_REG, 0x02000000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x01000000); + /* unreset */ + mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002); + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); + mmio_write_32(CRG_PEREN4_REG, 0x000000a8); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP); + /* set ivp 533MHz, 1600MHz / 3 */ + mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800); +} + +static void set_audio_power_up(void) +{ + unsigned int ret; + int timeout = 100; + /* mtcmos on */ + mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); + mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); + mmio_write_32(CRG_PEREN0_REG, 0x04000000); + mmio_write_32(CRG_PEREN5_REG, 0x00000080); + mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); + udelay(1); + /* clk disable */ + mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f); + mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000); + mmio_write_32(CRG_PERDIS5_REG, 0x00000080); + mmio_write_32(CRG_PERDIS0_REG, 0x04000000); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000); + mmio_write_32(CRG_CLKDIV19_REG, 0x80100000); + udelay(1); + /* iso disable */ + mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001); + udelay(1); + /* unreset */ + mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001); + mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); + mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); + mmio_write_32(CRG_PEREN0_REG, 0x04000000); + mmio_write_32(CRG_PEREN5_REG, 0x00000080); + mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); + /* bus idle clear */ + mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000); + for (;;) { + ret = mmio_read_32(SCTRL_SCPERSTAT6_REG); + if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0)) + break; + udelay(1); + timeout--; + if (timeout <= 0) { + WARN("%s timeout\n", __func__); + break; + } + } + mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000); +} + +static void set_pcie_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010); + udelay(100); + /* clk enable */ + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); + mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); + mmio_write_32(CRG_PEREN7_REG, 0x000003a0); + udelay(1); + /* clk disable */ + mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000); + mmio_write_32(CRG_PERDIS7_REG, 0x000003a0); + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000); + udelay(1); + /* iso disable */ + mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000); + /* clk enable */ + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); + mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); + mmio_write_32(CRG_PEREN7_REG, 0x000003a0); +} + +static void ispfunc_enable(void) +{ + /* enable ispfunc. Otherwise powerup isp_srt causes exception. */ + mmio_write_32(0xfff35000, 0x00000008); + mmio_write_32(0xfff35460, 0xc004ffff); + mmio_write_32(0xfff35030, 0x02000000); + mdelay(10); +} + +static void isps_control_clock(int flag) +{ + unsigned int ret; + + /* flag: 0 -- disable clock, 1 -- enable clock */ + if (flag) { + ret = mmio_read_32(0xe8420364); + ret |= 1; + mmio_write_32(0xe8420364, ret); + } else { + ret = mmio_read_32(0xe8420364); + ret &= ~1; + mmio_write_32(0xe8420364, ret); + } +} + +static void set_isp_srt_power_up(void) +{ + unsigned int ret; + + ispfunc_enable(); + /* reset */ + mmio_write_32(0xe8420374, 0x00000001); + mmio_write_32(0xe8420350, 0x00000000); + mmio_write_32(0xe8420358, 0x00000000); + /* mtcmos on */ + mmio_write_32(0xfff35150, 0x00400000); + udelay(100); + /* clk enable */ + isps_control_clock(1); + udelay(1); + isps_control_clock(0); + udelay(1); + /* iso disable */ + mmio_write_32(0xfff35148, 0x08000000); + /* unreset */ + ret = mmio_read_32(0xe8420374); + ret &= ~0x1; + mmio_write_32(0xe8420374, ret); + /* clk enable */ + isps_control_clock(1); + /* enable clock gating for accessing csi registers */ + mmio_write_32(0xe8420010, ~0); +} + +void hikey960_regulator_enable(void) +{ + set_vivobus_power_up(); + hikey960_enable_ppll3(); + set_dss_power_up(); + set_vcodec_power_up(); + set_vdec_power_up(); + set_venc_power_up(); + set_isp_power_up(); + set_ivp_power_up(); + set_audio_power_up(); + set_pcie_power_up(); + set_isp_srt_power_up(); + + /* set ISP_CORE_CTRL_S to unsecure mode */ + mmio_write_32(0xe8583800, 0x7); + /* set ISP_SUB_CTRL_S to unsecure mode */ + mmio_write_32(0xe8583804, 0xf); +} + +void hikey960_tzc_init(void) +{ + mmio_write_32(TZC_EN0_REG, 0x7fbff066); + mmio_write_32(TZC_EN1_REG, 0xfffff5fc); + mmio_write_32(TZC_EN2_REG, 0x0007005c); + mmio_write_32(TZC_EN3_REG, 0x37030700); + mmio_write_32(TZC_EN4_REG, 0xf63fefae); + mmio_write_32(TZC_EN5_REG, 0x000410fd); + mmio_write_32(TZC_EN6_REG, 0x0063ff68); + mmio_write_32(TZC_EN7_REG, 0x030000f3); + mmio_write_32(TZC_EN8_REG, 0x00000007); +} + +void hikey960_peri_init(void) +{ + /* unreset */ + mmio_setbits_32(CRG_PERRSTDIS4_REG, 1); +} + +void hikey960_pinmux_init(void) +{ + unsigned int id; + + hikey960_read_boardid(&id); + if (id == 5301) { + /* hikey960 hardware v2 */ + /* GPIO150: LED */ + mmio_write_32(IOMG_FIX_006_REG, 0); + /* GPIO151: LED */ + mmio_write_32(IOMG_FIX_007_REG, 0); + /* GPIO189: LED */ + mmio_write_32(IOMG_AO_011_REG, 0); + /* GPIO190: LED */ + mmio_write_32(IOMG_AO_012_REG, 0); + /* GPIO46 */ + mmio_write_32(IOMG_044_REG, 0); + /* GPIO202 */ + mmio_write_32(IOMG_AO_023_REG, 0); + /* GPIO206 */ + mmio_write_32(IOMG_AO_026_REG, 0); + /* GPIO219 - PD pullup */ + mmio_write_32(IOMG_AO_039_REG, 0); + mmio_write_32(IOCG_AO_043_REG, 1 << 0); + } + /* GPIO005 - PMU SSI, 10mA */ + mmio_write_32(IOCG_006_REG, 2 << 4); + /* GPIO213 - PCIE_CLKREQ_N */ + mmio_write_32(IOMG_AO_033_REG, 1); +} + +void hikey960_gpio_init(void) +{ + pl061_gpio_init(); + pl061_gpio_register(GPIO0_BASE, 0); + pl061_gpio_register(GPIO1_BASE, 1); + pl061_gpio_register(GPIO2_BASE, 2); + pl061_gpio_register(GPIO3_BASE, 3); + pl061_gpio_register(GPIO4_BASE, 4); + pl061_gpio_register(GPIO5_BASE, 5); + pl061_gpio_register(GPIO6_BASE, 6); + pl061_gpio_register(GPIO7_BASE, 7); + pl061_gpio_register(GPIO8_BASE, 8); + pl061_gpio_register(GPIO9_BASE, 9); + pl061_gpio_register(GPIO10_BASE, 10); + pl061_gpio_register(GPIO11_BASE, 11); + pl061_gpio_register(GPIO12_BASE, 12); + pl061_gpio_register(GPIO13_BASE, 13); + pl061_gpio_register(GPIO14_BASE, 14); + pl061_gpio_register(GPIO15_BASE, 15); + pl061_gpio_register(GPIO16_BASE, 16); + pl061_gpio_register(GPIO17_BASE, 17); + pl061_gpio_register(GPIO18_BASE, 18); + pl061_gpio_register(GPIO19_BASE, 19); + pl061_gpio_register(GPIO20_BASE, 20); + pl061_gpio_register(GPIO21_BASE, 21); + pl061_gpio_register(GPIO22_BASE, 22); + pl061_gpio_register(GPIO23_BASE, 23); + pl061_gpio_register(GPIO24_BASE, 24); + pl061_gpio_register(GPIO25_BASE, 25); + pl061_gpio_register(GPIO26_BASE, 26); + pl061_gpio_register(GPIO27_BASE, 27); + pl061_gpio_register(GPIO28_BASE, 28); + + /* PCIE_PERST_N output low */ + gpio_set_direction(89, GPIO_DIR_OUT); + gpio_set_value(89, GPIO_LEVEL_LOW); +} diff --git a/plat/hisilicon/hikey960/hikey960_boardid.c b/plat/hisilicon/hikey960/hikey960_boardid.c new file mode 100644 index 0000000..1e1126f --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_boardid.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#include <hi3660.h> +#include "hikey960_private.h" + +#define ADC_ADCIN0 0 +#define ADC_ADCIN1 1 +#define ADC_ADCIN2 2 + +#define HKADC_DATA_GRADE0 0 +#define HKADC_DATA_GRADE1 100 +#define HKADC_DATA_GRADE2 300 +#define HKADC_DATA_GRADE3 500 +#define HKADC_DATA_GRADE4 700 +#define HKADC_DATA_GRADE5 900 +#define HKADC_DATA_GRADE6 1100 +#define HKADC_DATA_GRADE7 1300 +#define HKADC_DATA_GRADE8 1500 +#define HKADC_DATA_GRADE9 1700 +#define HKADC_DATA_GRADE10 1800 + +#define BOARDID_VALUE0 0 +#define BOARDID_VALUE1 1 +#define BOARDID_VALUE2 2 +#define BOARDID_VALUE3 3 +#define BOARDID_VALUE4 4 +#define BOARDID_VALUE5 5 +#define BOARDID_VALUE6 6 +#define BOARDID_VALUE7 7 +#define BOARDID_VALUE8 8 +#define BOARDID_VALUE9 9 +#define BOARDID_UNKNOWN 0xF + +#define BOARDID3_BASE 5 + + +static void init_adc(void) +{ + /* reset hkadc */ + mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI); + /* wait a few clock cycles */ + udelay(2); + mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI); + udelay(2); + /* enable hkadc clock */ + mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI); + udelay(2); + mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI); + udelay(2); +} + +static int get_adc(unsigned int channel, unsigned int *value) +{ + unsigned int data, value1, value0; + + if (channel > HKADC_CHANNEL_MAX) { + WARN("invalid channel:%d\n", channel); + return -EFAULT; + } + /* configure the read/write operation for external HKADC */ + mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel); + mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE); + mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE); + /* configure the number of accessing registers */ + mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE); + /* configure delay of accessing registers */ + mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE); + mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE); + + /* start HKADC */ + mmio_write_32(HKADC_DSP_START_REG, 1); + do { + data = mmio_read_32(HKADC_DSP_START_REG); + } while (data & 1); + + /* convert AD result */ + value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff; + value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff; + + data = ((value1 << 4) & HKADC_VALUE_HIGH) | + ((value0 >> 4) & HKADC_VALUE_LOW); + *value = data; + return 0; +} + +static int get_value(unsigned int channel, unsigned int *value) +{ + int ret; + + ret = get_adc(channel, value); + if (ret) + return ret; + + /* convert ADC value to micro-volt */ + ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY; + *value = ret; + return 0; +} + +static int adcin_data_remap(unsigned int adcin_value) +{ + int ret; + + if (adcin_value < HKADC_DATA_GRADE1) + ret = BOARDID_VALUE0; + else if (adcin_value < HKADC_DATA_GRADE2) + ret = BOARDID_VALUE1; + else if (adcin_value < HKADC_DATA_GRADE3) + ret = BOARDID_VALUE2; + else if (adcin_value < HKADC_DATA_GRADE4) + ret = BOARDID_VALUE3; + else if (adcin_value < HKADC_DATA_GRADE5) + ret = BOARDID_VALUE4; + else if (adcin_value < HKADC_DATA_GRADE6) + ret = BOARDID_VALUE5; + else if (adcin_value < HKADC_DATA_GRADE7) + ret = BOARDID_VALUE6; + else if (adcin_value < HKADC_DATA_GRADE8) + ret = BOARDID_VALUE7; + else if (adcin_value < HKADC_DATA_GRADE9) + ret = BOARDID_VALUE8; + else if (adcin_value < HKADC_DATA_GRADE10) + ret = BOARDID_VALUE9; + else + ret = BOARDID_UNKNOWN; + return ret; +} + +int hikey960_read_boardid(unsigned int *id) +{ + unsigned int adcin0, adcin1, adcin2; + unsigned int adcin0_remap, adcin1_remap, adcin2_remap; + + assert(id != NULL); + + init_adc(); + + /* read ADC channel0 data */ + get_value(ADC_ADCIN0, &adcin0); + adcin0_remap = adcin_data_remap(adcin0); + if (adcin0_remap == BOARDID_UNKNOWN) + return -EINVAL; + /* read ADC channel1 data */ + get_value(ADC_ADCIN1, &adcin1); + adcin1_remap = adcin_data_remap(adcin1); + if (adcin1_remap == BOARDID_UNKNOWN) + return -EINVAL; + /* read ADC channel2 data */ + get_value(ADC_ADCIN2, &adcin2); + adcin2_remap = adcin_data_remap(adcin2); + if (adcin2_remap == BOARDID_UNKNOWN) + return -EINVAL; + *id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) + + (adcin1_remap * 10) + adcin0_remap; + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_def.h b/plat/hisilicon/hikey960/hikey960_def.h new file mode 100644 index 0000000..e103cf4 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_def.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY960_DEF_H +#define HIKEY960_DEF_H + +#include <common/tbbr/tbbr_img_def.h> +#include <plat/common/common_def.h> + +#define DDR_BASE 0x0 +#define DDR_SIZE 0xE0000000 + +#define DEVICE_BASE 0xE0000000 +#define DEVICE_SIZE 0x20000000 + +/* Memory location options for TSP */ +#define HIKEY960_SRAM_ID 0 +#define HIKEY960_DRAM_ID 1 + +/* + * DDR for TEE (80MB from 0x3E00000-0x43000FFF) is divided into several + * regions: + * - SPMC manifest (4KB at the top) used by SPMC_AT_EL3 and the TEE + * - Datastore for SPMC_AT_EL3 (4MB at the top) used by BL31 + * - Secure DDR (default is the top 60MB) used by OP-TEE + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR (8MB) reserved for OP-TEE's future use + */ +#define DDR_SEC_SIZE 0x03C00000 /* reserve 60MB secure memory */ +#define DDR_SEC_BASE 0x3F000000 +#define DDR2_SEC_SIZE 0x00400000 /* SPMC_AT_EL3: 4MB for BL31 RAM2 */ +#define DDR2_SEC_BASE 0x42C00000 +#define DDR_SEC_CONFIG_SIZE 0x00001000 /* SPMC_AT_EL3: SPMC manifest */ +#define DDR_SEC_CONFIG_BASE 0x43000000 + +#define DDR_SDP_SIZE 0x00400000 +#define DDR_SDP_BASE (DDR_SEC_BASE - 0x400000 /* align */ - \ + DDR_SDP_SIZE) + +/* + * PL011 related constants + */ +#define PL011_UART5_BASE 0xFDF05000 +#define PL011_UART6_BASE 0xFFF32000 +#define PL011_BAUDRATE 115200 +#define PL011_UART_CLK_IN_HZ 19200000 + +#define UFS_BASE 0 + +#define HIKEY960_UFS_DESC_BASE 0x20000000 +#define HIKEY960_UFS_DESC_SIZE 0x00200000 /* 2MB */ +#define HIKEY960_UFS_DATA_BASE 0x10000000 +#define HIKEY960_UFS_DATA_SIZE 0x0A000000 /* 160MB */ + +#if defined(SPMC_AT_EL3) +/* + * Number of Secure Partitions supported. + * SPMC at EL3, uses this count to configure the maximum number of supported + * secure partitions. + */ +#define SECURE_PARTITION_COUNT 1 + +/* + * Number of Nwld Partitions supported. + * SPMC at EL3, uses this count to configure the maximum number of supported + * nwld partitions. + */ +#define NS_PARTITION_COUNT 1 +/* + * Number of Logical Partitions supported. + * SPMC at EL3, uses this count to configure the maximum number of supported + * logical partitions. + */ +#define MAX_EL3_LP_DESCS_COUNT 1 + +#endif /* SPMC_AT_EL3 */ + +#endif /* HIKEY960_DEF_H */ diff --git a/plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c b/plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c new file mode 100644 index 0000000..b9e4f86 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <services/el3_spmc_logical_sp.h> +#include <services/ffa_svc.h> +#include <smccc_helpers.h> + +#define LP_PARTITION_ID 0xC001 +#define LP_UUID {0x47a3bf57, 0xe98e43ad, 0xb7db524f, 0x1588f4e3} + +/* Our Logical SP currently only supports receipt of direct messaging. */ +#define PARTITION_PROPERTIES FFA_PARTITION_DIRECT_REQ_RECV + +static int32_t sp_init(void) +{ + INFO("LSP: Init function called.\n"); + return 0; +} + +static uint64_t handle_ffa_direct_request(uint32_t smc_fid, bool secure_origin, + uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + uint64_t ret; + + /* Determine if we have a 64 or 32 direct request. */ + if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC32) { + ret = FFA_MSG_SEND_DIRECT_RESP_SMC32; + } else if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC64) { + ret = FFA_MSG_SEND_DIRECT_RESP_SMC64; + } else { + panic(); /* Unknown SMC. */ + } + /* + * Handle the incoming request. For testing purposes we echo the + * incoming message. + */ + INFO("Logical Partition: Received Direct Request from %s world!\n", + secure_origin ? "Secure" : "Normal"); + + /* + * Logical SP's must always send a direct response so we can populate + * our response directly. + */ + SMC_RET8(handle, ret, 0, 0, x4, 0, 0, 0, 0); +} + +/* Register logical partition */ +DECLARE_LOGICAL_PARTITION( + my_logical_partition, + sp_init, /* Init Function */ + LP_PARTITION_ID, /* FF-A Partition ID */ + LP_UUID, /* UUID */ + PARTITION_PROPERTIES, /* Partition Properties. */ + handle_ffa_direct_request /* Callback for direct requests. */ +); diff --git a/plat/hisilicon/hikey960/hikey960_image_load.c b/plat/hisilicon/hikey960/hikey960_image_load.c new file mode 100644 index 0000000..9a5b74e --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_image_load.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + + +/******************************************************************************* + * ARM helper function to return the list of executable images. Since the default + * descriptors are allocated within BL2 RW memory, this prevents BL31/BL32 + * overlay of BL2 memory. Hence this function also copies the descriptors to a + * pre-allocated memory indicated by ARM_BL2_MEM_DESC_BASE. + ******************************************************************************/ +struct bl_params *hikey960_get_next_bl_params(void) +{ + bl_params_t *next_bl_params; + + next_bl_params = get_next_bl_params_from_mem_params_desc(); + assert(next_bl_params != NULL); + + populate_next_bl_params_config(next_bl_params); + + return next_bl_params; +} + + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return hikey960_get_next_bl_params(); +} diff --git a/plat/hisilicon/hikey960/hikey960_io_storage.c b/plat/hisilicon/hikey960/hikey960_io_storage.c new file mode 100644 index 0000000..475e416 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_io_storage.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/ufs.h> +#include <drivers/io/io_block.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_fip.h> +#include <drivers/io/io_memmap.h> +#include <drivers/io/io_storage.h> +#include <drivers/partition/partition.h> +#include <lib/mmio.h> +#include <lib/semihosting.h> +#include <tools_share/firmware_image_package.h> + +#include "hikey960_def.h" +#include "hikey960_private.h" + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; +static uintptr_t ufs_dev_handle, fip_dev_handle; + +static int check_ufs(const uintptr_t spec); +static int check_fip(const uintptr_t spec); +size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); +size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); + +static io_block_spec_t ufs_fip_spec; + +static const io_block_spec_t ufs_gpt_spec = { + .offset = 0, + .length = PLAT_PARTITION_BLOCK_SIZE * + (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), +}; + +/* Fastboot serial number stored within first UFS device blocks */ +static const io_block_spec_t ufs_fastboot_spec = { + .offset = UFS_BASE, + .length = 1 << 20, +}; + +static const io_block_dev_spec_t ufs_dev_spec = { + /* It's used as temp buffer in block driver. */ + .buffer = { + .offset = HIKEY960_UFS_DATA_BASE, + .length = HIKEY960_UFS_DATA_SIZE, + }, + .ops = { + .read = ufs_read_lun3_blks, + .write = ufs_write_lun3_blks, + }, + .block_size = UFS_BLOCK_SIZE, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +#ifdef SPD_spmd +static const io_uuid_spec_t bl32_tos_fw_spec = { + .uuid = UUID_TOS_FW_CONFIG, +}; +#endif + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &ufs_dev_handle, + (uintptr_t)&ufs_fip_spec, + check_ufs + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_bl2_uuid_spec, + check_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + check_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + check_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + check_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + check_fip + }, + +#ifdef SPD_spmd + [TOS_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_tos_fw_spec, + check_fip + }, +#endif + + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + check_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_key_cert_uuid_spec, + check_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_cert_uuid_spec, + check_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + check_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ + [GPT_IMAGE_ID] = { + &ufs_dev_handle, + (uintptr_t)&ufs_gpt_spec, + check_ufs + }, +}; + +static int check_ufs(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(ufs_dev_handle, spec, &local_handle); + if (result == 0) + io_close(local_handle); + } + return result; +} + +static int check_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +int hikey960_load_serialno(uint64_t *serno) +{ + int result; + size_t len = 0; + uintptr_t local_handle; + uint64_t buf[HIKEY960_SERIAL_NUMBER_SIZE / sizeof(uint64_t)]; + + if (serno == NULL) { + return -1; + } + + result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); + if (result != 0) { + return result; + } + + result = io_open(ufs_dev_handle, + (uintptr_t)&ufs_fastboot_spec, &local_handle); + if (result != 0) { + return result; + } + + result = io_seek(local_handle, IO_SEEK_SET, + HIKEY960_SERIAL_NUMBER_LBA * UFS_BLOCK_SIZE); + if (result != 0) { + goto closing; + } + + result = io_read(local_handle, (uintptr_t)buf, + HIKEY960_SERIAL_NUMBER_SIZE, &len); + if (result != 0) { + goto closing; + } + + if (len != HIKEY960_SERIAL_NUMBER_SIZE) { + result = -1; + goto closing; + } + + /* UEFI fastboot app stores a 16 bytes blob */ + /* We extract only relevant 8 bytes serial number */ + *serno = buf[1]; + +closing: + io_close(local_handle); + return result; +} + +void hikey960_io_setup(void) +{ + int result; + + result = register_io_dev_block(&ufs_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, + &ufs_dev_handle); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); + assert(result == 0); + + /* Ignore improbable errors in release builds */ + (void)result; +} + +int hikey960_set_fip_addr(unsigned int image_id, const char *name) +{ + const partition_entry_t *entry; + + if (ufs_fip_spec.length == 0) { + partition_init(GPT_IMAGE_ID); + entry = get_partition_entry(name); + if (entry == NULL) { + ERROR("Could NOT find the %s partition!\n", name); + return -ENOENT; + } + ufs_fip_spec.offset = entry->start; + ufs_fip_spec.length = entry->length; + } + return 0; +} + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} + +size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) +{ + return ufs_read_blocks(3, lba, buf, size); +} + +size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) +{ + return ufs_write_blocks(3, lba, buf, size); +} diff --git a/plat/hisilicon/hikey960/hikey960_mcu_load.c b/plat/hisilicon/hikey960/hikey960_mcu_load.c new file mode 100644 index 0000000..b9ae313 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_mcu_load.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#include <hi3660.h> + +#define ADDR_CONVERT(addr) ((addr) < 0x40000 ? \ + (addr) + 0xFFF30000 : \ + (addr) + 0x40000000) + +static void fw_data_init(void) +{ + unsigned long data_head_addr; + unsigned int *data_addr; + + data_head_addr = mmio_read_32((uintptr_t) HISI_DATA_HEAD_BASE) + 0x14; + data_addr = (unsigned int *) ADDR_CONVERT(data_head_addr); + + memcpy((void *)HISI_DATA0_BASE, + (const void *)(unsigned long)ADDR_CONVERT(data_addr[0]), + HISI_DATA0_SIZE); + memcpy((void *)HISI_DATA1_BASE, + (const void *)(unsigned long)ADDR_CONVERT(data_addr[1]), + HISI_DATA1_SIZE); +} + +int load_lpm3(void) +{ + INFO("start fw loading\n"); + + fw_data_init(); + + flush_dcache_range((uintptr_t)HISI_RESERVED_MEM_BASE, + HISI_RESERVED_MEM_SIZE); + + sev(); + sev(); + + INFO("fw load success\n"); + + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c new file mode 100644 index 0000000..f836508 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_pm.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/pl011.h> +#include <drivers/arm/pl061_gpio.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> + +#include <hi3660.h> +#include <hi3660_crg.h> + +#include "drivers/pwrc/hisi_pwrc.h" +#include "hikey960_def.h" +#include "hikey960_private.h" + +#define CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +#define DMAC_GLB_REG_SEC 0x694 +#define AXI_CONF_BASE 0x820 + +static unsigned int uart_base; +static console_t console; +static uintptr_t hikey960_sec_entrypoint; + +static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) +{ + unsigned long scr; + + scr = read_scr_el3(); + + /* Enable Physical IRQ and FIQ to wake the CPU */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + /* Add barrier before CPU enter WFI state */ + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisazion of + * scr_el3 is done by eret while el3_exit to save some + * execution cycles. + */ + write_scr_el3(scr); +} + +static int hikey960_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + int cluster_stat = cluster_is_powered_on(cluster); + + hisi_set_cpu_boot_flag(cluster, core); + + mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), + hikey960_sec_entrypoint >> 2); + + if (cluster_stat) + hisi_powerup_core(cluster, core); + else + hisi_powerup_cluster(cluster, core); + + return PSCI_E_SUCCESS; +} + +static void +hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void hikey960_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + clr_ex(); + isb(); + dsbsy(); + + gicv2_cpuif_disable(); + + hisi_clear_cpu_boot_flag(cluster, core); + hisi_powerdn_core(cluster, core); + + /* check if any core is powered up */ + if (hisi_test_cpu_down(cluster, core)) { + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + isb(); + dsbsy(); + + hisi_powerdn_cluster(cluster, core); + } +} + +static void __dead2 hikey960_system_off(void) +{ + gpio_set_direction(176, GPIO_DIR_OUT); + gpio_set_value(176, GPIO_LEVEL_LOW); + panic(); +} + +static void __dead2 hikey960_system_reset(void) +{ + dsb(); + isb(); + mdelay(2000); + mmio_write_32(SCTRL_SCPEREN1_REG, + SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS); + mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef); + panic(); +} + +int hikey960_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = + PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + PLAT_MAX_OFF_STATE; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + clr_ex(); + isb(); + dsbsy(); + + gicv2_cpuif_disable(); + + hisi_cpuidle_lock(cluster, core); + hisi_set_cpuidle_flag(cluster, core); + hisi_cpuidle_unlock(cluster, core); + + mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), + hikey960_sec_entrypoint >> 2); + + hisi_enter_core_idle(cluster, core); + } + + /* Perform the common cluster specific operations */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_cpuidle_lock(cluster, core); + hisi_disable_pdc(cluster); + + /* check if any core is powered up */ + if (hisi_test_pwrdn_allcores(cluster, core)) { + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + isb(); + dsbsy(); + + /* mask the pdc wakeup irq, then + * enable pdc to power down the core + */ + hisi_pdc_mask_cluster_wakeirq(cluster); + hisi_enable_pdc(cluster); + + hisi_cpuidle_unlock(cluster, core); + + /* check the SR flag bit to determine + * CLUSTER_IDLE_IPC or AP_SR_IPC to send + */ + if (hisi_test_ap_suspend_flag()) + hisi_enter_ap_suspend(cluster, core); + else + hisi_enter_cluster_idle(cluster, core); + } else { + /* enable pdc */ + hisi_enable_pdc(cluster); + hisi_cpuidle_unlock(cluster, core); + } + } +} + +static void hikey960_sr_dma_reinit(void) +{ + unsigned int ctr = 0; + + mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3); + + /* 1~15 channel is set non_secure */ + for (ctr = 1; ctr <= 15; ctr++) + mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40), + (1 << 6) | (1 << 18)); +} + +static void +hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + /* Nothing to be done on waking up from retention from CPU level */ + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + hisi_cpuidle_lock(cluster, core); + hisi_clear_cpuidle_flag(cluster, core); + hisi_cpuidle_unlock(cluster, core); + + if (hisi_test_ap_suspend_flag()) { + hikey960_sr_dma_reinit(); + gicv2_cpuif_enable(); + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + } + + hikey960_pwr_domain_on_finish(target_state); +} + +static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static const plat_psci_ops_t hikey960_psci_ops = { + .cpu_standby = hikey960_pwr_domain_standby, + .pwr_domain_on = hikey960_pwr_domain_on, + .pwr_domain_on_finish = hikey960_pwr_domain_on_finish, + .pwr_domain_off = hikey960_pwr_domain_off, + .pwr_domain_suspend = hikey960_pwr_domain_suspend, + .pwr_domain_suspend_finish = hikey960_pwr_domain_suspend_finish, + .system_off = hikey960_system_off, + .system_reset = hikey960_system_reset, + .validate_power_state = hikey960_validate_power_state, + .validate_ns_entrypoint = hikey960_validate_ns_entrypoint, + .get_sys_suspend_power_state = hikey960_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + unsigned int id = 0; + int ret; + + ret = hikey960_read_boardid(&id); + if (ret == 0) { + if (id == 5300U) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + } else { + uart_base = PL011_UART6_BASE; + } + + hikey960_sec_entrypoint = sec_entrypoint; + + INFO("%s: sec_entrypoint=0x%lx\n", __func__, + (unsigned long)hikey960_sec_entrypoint); + + /* + * Initialize PSCI ops struct + */ + *psci_ops = &hikey960_psci_ops; + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_private.h b/plat/hisilicon/hikey960/hikey960_private.h new file mode 100644 index 0000000..742725c --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_private.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY960_PRIVATE_H +#define HIKEY960_PRIVATE_H + +#include <common/bl_common.h> + +/* Fastboot serial number */ +#define HIKEY960_SERIAL_NUMBER_LBA (UFS_BASE + 20) +#define HIKEY960_SERIAL_NUMBER_SIZE 16 + +/* + * Function and variable prototypes + */ +void hikey960_init_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void hikey960_init_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void hikey960_io_setup(void); +int hikey960_read_boardid(unsigned int *id); +int hikey960_set_fip_addr(unsigned int image_id, const char *name); +int hikey960_load_serialno(uint64_t *serno); +void hikey960_clk_init(void); +void hikey960_pmu_init(void); +void hikey960_regulator_enable(void); +void hikey960_tzc_init(void); +void hikey960_peri_init(void); +void hikey960_pinmux_init(void); +void hikey960_gpio_init(void); +void set_retention_ticks(unsigned int val); +void clr_retention_ticks(unsigned int val); +void clr_ex(void); +void nop(void); + +/******************************************************************************* + * Struct for parameters received from BL2 + ******************************************************************************/ +typedef struct plat_params_from_bl2 { + /* Fastboot serial number gathered from UFS */ + uint64_t fastboot_serno; +} plat_params_from_bl2_t; + +#endif /* HIKEY960_PRIVATE_H */ diff --git a/plat/hisilicon/hikey960/hikey960_rotpk.S b/plat/hisilicon/hikey960/hikey960_rotpk.S new file mode 100644 index 0000000..f230ed6 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_rotpk.S @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global hikey960_rotpk_hash + .global hikey960_rotpk_hash_end + .section .rodata.hikey960_rotpk_hash, "a" +hikey960_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +hikey960_rotpk_hash_end: diff --git a/plat/hisilicon/hikey960/hikey960_tbbr.c b/plat/hisilicon/hikey960/hikey960_tbbr.c new file mode 100644 index 0000000..ed4da3b --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_tbbr.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> + +extern char hikey960_rotpk_hash[], hikey960_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = hikey960_rotpk_hash; + *key_len = hikey960_rotpk_hash_end - hikey960_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/plat/hisilicon/hikey960/hikey960_topology.c b/plat/hisilicon/hikey960/hikey960_topology.c new file mode 100644 index 0000000..a242bb1 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_topology.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <arch.h> +#include <lib/psci/psci.h> + +/* + * The HiKey power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char hikey960_power_domain_tree_desc[] = { + /* Number of root nodes */ + 1, + /* Number of clusters */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, + /* Number of children for the second cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the HiKey topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hikey960_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h new file mode 100644 index 0000000..17b495f --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef HI3660_H +#define HI3660_H + +#include <hi3660_crg.h> +#include <hi3660_hkadc.h> +#include <hi3660_mem_map.h> + +#define ASP_CFG_REG_BASE 0xE804E000 + +#define ASP_CFG_MMBUF_CTRL_REG (ASP_CFG_REG_BASE + 0x148) + +#define LP_RAM_BASE 0xFFF50000 + +#define SCTRL_REG_BASE 0xFFF0A000 + +#define SCTRL_CONTROL_REG (SCTRL_REG_BASE + 0x000) +#define SCTRL_CONTROL_SYS_MODE(x) (((x) & 0xf) << 3) +#define SCTRL_CONTROL_SYS_MODE_NORMAL ((1 << 2) << 3) +#define SCTRL_CONTROL_SYS_MODE_SLOW ((1 << 1) << 3) +#define SCTRL_CONTROL_SYS_MODE_MASK (0xf << 3) +#define SCTRL_CONTROL_MODE_CTRL_NORMAL (1 << 2) +#define SCTRL_CONTROL_MODE_CTRL_SLOW (1 << 1) +#define SCTRL_CONTROL_MODE_CTRL_MASK 0x7 + +#define SCTRL_SCSYSSTAT_REG (SCTRL_REG_BASE + 0x004) + +#define SCTRL_DEEPSLEEPED_REG (SCTRL_REG_BASE + 0x008) +#define SCTRL_EFUSE_USB_MASK (1 << 30) +#define SCTRL_EFUSE_USB_PLL (1 << 30) +#define SCTRL_EFUSE_USB_ABB (0 << 30) +#define SCTRL_EFUSE_UFS_MASK (3 << 6) +#define SCTRL_EFUSE_UFS_PLL (1 << 6) +#define SCTRL_EFUSE_UFS_ABB (0 << 6) + +#define SCTRL_SCISOEN_REG (SCTRL_REG_BASE + 0x040) +#define SCTRL_SCISODIS_REG (SCTRL_REG_BASE + 0x044) +#define SCISO_MMBUFISO (1 << 3) + +#define SCTRL_SCPWREN_REG (SCTRL_REG_BASE + 0x060) +#define SCPWREN_MMBUFPWREN (1 << 3) + +#define SCTRL_PLL_CTRL0_REG (SCTRL_REG_BASE + 0x100) +#define SCTRL_PLL0_POSTDIV2(x) (((x) & 0x7) << 23) +#define SCTRL_PLL0_POSTDIV1(x) (((x) & 0x7) << 20) +#define SCTRL_PLL0_FBDIV(x) (((x) & 0xfff) << 8) +#define SCTRL_PLL0_REFDIV(x) (((x) & 0x3f) << 2) +#define SCTRL_PLL0_EN (1 << 0) + +#define SCTRL_PLL_CTRL1_REG (SCTRL_REG_BASE + 0x104) +#define SCTRL_PLL0_CLK_NO_GATE (1 << 26) +#define SCTRL_PLL0_CFG_VLD (1 << 25) +#define SCTRL_PLL0_FRACDIV(x) ((x) & 0xFFFFFF) + +#define SCTRL_PLL_STAT_REG (SCTRL_REG_BASE + 0x10C) +#define SCTRL_PLL0_STAT (1 << 0) + +#define SCTRL_SCPEREN0_REG (SCTRL_REG_BASE + 0x160) +#define SCTRL_SCPERDIS0_REG (SCTRL_REG_BASE + 0x164) +#define SCTRL_SCPERSTAT0_REG (SCTRL_REG_BASE + 0x168) + +#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170) +#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174) +#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170) +#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174) +#define SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS (1u << 31) +#define SCPEREN_GT_PCLK_MMBUFCFG (1 << 25) +#define SCPEREN_GT_PCLK_MMBUF (1 << 23) +#define SCPEREN_GT_ACLK_MMBUF (1 << 22) +#define SCPEREN_GT_CLK_NOC_AOBUS2MMBUF (1 << 6) + +#define SCTRL_SCPEREN2_REG (SCTRL_REG_BASE + 0x190) +#define SCTRL_SCPERDIS2_REG (SCTRL_REG_BASE + 0x194) +#define SCTRL_SCPERSTAT2_REG (SCTRL_REG_BASE + 0x198) +#define SCTRL_SCPERRSTEN0_REG (SCTRL_REG_BASE + 0x200) +#define SCTRL_SCPERRSTDIS0_REG (SCTRL_REG_BASE + 0x204) +#define SCTRL_SCPERRSTSTAT0_REG (SCTRL_REG_BASE + 0x208) +#define SCTRL_SCPERRSTEN1_REG (SCTRL_REG_BASE + 0x20C) +#define SCTRL_SCPERRSTDIS1_REG (SCTRL_REG_BASE + 0x210) +#define SCTRL_SCPERRSTSTAT1_REG (SCTRL_REG_BASE + 0x214) +#define IP_RST_MMBUFCFG (1 << 12) +#define IP_RST_MMBUF (1 << 11) + +#define SCTRL_SCPERRSTEN2_REG (SCTRL_REG_BASE + 0x218) +#define SCTRL_SCPERRSTDIS2_REG (SCTRL_REG_BASE + 0x21C) +#define SCTRL_SCPERRSTSTAT2_REG (SCTRL_REG_BASE + 0x220) + +#define SCTRL_SCCLKDIV2_REG (SCTRL_REG_BASE + 0x258) +#define SEL_CLK_MMBUF_MASK (0x3 << 8) +#define SEL_CLK_MMBUF_PLL0 (0x3 << 8) +#define SCCLKDIV2_GT_PCLK_MMBUF (1 << 7) + +#define SCTRL_SCCLKDIV4_REG (SCTRL_REG_BASE + 0x260) +#define GT_MMBUF_SYS (1 << 13) +#define GT_MMBUF_FLL (1 << 12) +#define GT_PLL_CLK_MMBUF (1 << 11) + +#define SCTRL_SCCLKDIV6_REG (SCTRL_REG_BASE + 0x268) + +#define SCTRL_SCPERCTRL7_REG (SCTRL_REG_BASE + 0x31C) +#define SCTRL_SCPERSTAT6_REG (SCTRL_REG_BASE + 0x378) + +#define SCTRL_SCINNERSTAT_REG (SCTRL_REG_BASE + 0x3A0) +#define EMMC_UFS_SEL (1 << 15) + +#define SCTRL_BAK_DATA0_REG (SCTRL_REG_BASE + 0x40C) +#define SCTRL_BAK_DATA4_REG (SCTRL_REG_BASE + 0x41C) + +#define SCTRL_LPMCU_CLKEN_REG (SCTRL_REG_BASE + 0x480) +#define SCTRL_LPMCU_CLKDIS_REG (SCTRL_REG_BASE + 0x484) +#define SCTRL_LPMCU_RSTEN_REG (SCTRL_REG_BASE + 0x500) +#define SCTRL_LPMCU_RSTDIS_REG (SCTRL_REG_BASE + 0x504) +#define DDRC_SOFT_BIT (1 << 6) +#define DDRC_CLK_BIT (1 << 5) + +#define SCTRL_SCPEREN0_SEC_REG (SCTRL_REG_BASE + 0x900) +#define SCTRL_SCPERDIS0_SEC_REG (SCTRL_REG_BASE + 0x904) +#define MMBUF_SEC_CTRL_MASK (0xfff << 20) +#define MMBUF_SEC_CTRL(x) (((x) & 0xfff) << 20) + +#define SCTRL_PERRSTEN1_SEC_REG (SCTRL_REG_BASE + 0xA50) +#define SCTRL_PERRSTDIS1_SEC_REG (SCTRL_REG_BASE + 0xA54) +#define SCTRL_PERRSTSTAT1_SEC_REG (SCTRL_REG_BASE + 0xA58) +#define RST_ASP_SUBSYS_BIT (1 << 0) + +#define SCTRL_PERRSTEN2_SEC_REG (SCTRL_REG_BASE + 0xB50) +#define SCTRL_PERRSTDIS2_SEC_REG (SCTRL_REG_BASE + 0xB54) +#define SCTRL_PERRSTSTAT2_SEC_REG (SCTRL_REG_BASE + 0xB58) + +#define SCTRL_HISEECLKDIV_REG (SCTRL_REG_BASE + 0xC28) +#define SC_SEL_HISEE_PLL_MASK (1 << 4) +#define SC_SEL_HISEE_PLL0 (1 << 4) +#define SC_SEL_HISEE_PLL2 (0 << 4) +#define SC_DIV_HISEE_PLL_MASK (7 << 16) +#define SC_DIV_HISEE_PLL(x) ((x) & 0x7) + +#define SCTRL_SCSOCID0_REG (SCTRL_REG_BASE + 0xE00) + +#define PMC_REG_BASE 0xFFF31000 +#define PMC_PPLL1_CTRL0_REG (PMC_REG_BASE + 0x038) +#define PMC_PPLL1_CTRL1_REG (PMC_REG_BASE + 0x03C) +#define PMC_PPLL2_CTRL0_REG (PMC_REG_BASE + 0x040) +#define PMC_PPLL2_CTRL1_REG (PMC_REG_BASE + 0x044) +#define PMC_PPLL3_CTRL0_REG (PMC_REG_BASE + 0x048) +#define PMC_PPLL3_CTRL1_REG (PMC_REG_BASE + 0x04C) +#define PPLLx_LOCK (1 << 26) +#define PPLLx_WITHOUT_CLK_GATE (1 << 26) +#define PPLLx_CFG_VLD (1 << 25) +#define PPLLx_INT_MOD (1 << 24) +#define PPLLx_POSTDIV2_MASK (0x7 << 23) +#define PPLLx_POSTDIV2(x) (((x) & 0x7) << 23) +#define PPLLx_POSTDIV1_MASK (0x7 << 20) +#define PPLLx_POSTDIV1(x) (((x) & 0x7) << 20) +#define PPLLx_FRACDIV_MASK (0x00FFFFFF) +#define PPLLx_FRACDIV(x) ((x) & 0x00FFFFFF) +#define PPLLx_FBDIV_MASK (0xfff << 8) +#define PPLLx_FBDIV(x) (((x) & 0xfff) << 8) +#define PPLLx_REFDIV_MASK (0x3f << 2) +#define PPLLx_REFDIV(x) (((x) & 0x3f) << 2) +#define PPLLx_BP (1 << 1) +#define PPLLx_EN (1 << 0) + +#define PMC_DDRLP_CTRL_REG (PMC_REG_BASE + 0x30C) +#define DDRC_CSYSREQ_CFG(x) ((x) & 0xF) + +#define PMC_NOC_POWER_IDLEREQ_REG (PMC_REG_BASE + 0x380) +#define PMC_NOC_POWER_IDLEREQ_IVP (1 << 14) +#define PMC_NOC_POWER_IDLEREQ_DSS (1 << 13) +#define PMC_NOC_POWER_IDLEREQ_VENC (1 << 11) +#define PMC_NOC_POWER_IDLEREQ_VDEC (1 << 10) +#define PMC_NOC_POWER_IDLEREQ_ISP (1 << 5) +#define PMC_NOC_POWER_IDLEREQ_VCODEC (1 << 4) +#define DDRPHY_BYPASS_MODE (1 << 0) + +#define PMC_NOC_POWER_IDLEACK_REG (PMC_REG_BASE + 0x384) +#define PMC_NOC_POWER_IDLE_REG (PMC_REG_BASE + 0x388) + +#define PMU_SSI0_REG_BASE 0xFFF34000 + +#define PMU_SSI0_LDO8_CTRL0_REG (PMU_SSI0_REG_BASE + (0x68 << 2)) +#define LDO8_CTRL0_EN_1_8V 0x02 + +#define PMU_SSI0_CLK_TOP_CTRL7_REG (PMU_SSI0_REG_BASE + (0x10C << 2)) +#define NP_XO_ABB_DIG (1 << 1) + +#define LP_CONFIG_REG_BASE 0xFFF3F000 + +#define DMAC_BASE 0xFDF30000 + +#define CCI400_REG_BASE 0xE8100000 +#define CCI400_SL_IFACE3_CLUSTER_IX 0 +#define CCI400_SL_IFACE4_CLUSTER_IX 1 + +#define GICD_REG_BASE 0xE82B1000 +#define GICC_REG_BASE 0xE82B2000 +/* + * GIC400 interrupt handling related constants + */ +#define IRQ_SEC_PHY_TIMER 29 +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +#define IPC_REG_BASE 0xE896A000 +#define IPC_BASE (IPC_REG_BASE) + +#define IOMG_REG_BASE 0xE896C000 + +/* GPIO46: HUB 3.3V enable. active low */ +#define IOMG_044_REG (IOMG_REG_BASE + 0x0B0) +#define IOMG_UART5_RX_REG (IOMG_REG_BASE + 0x0BC) +#define IOMG_UART5_TX_REG (IOMG_REG_BASE + 0x0C0) + +#define IOCG_REG_BASE 0xE896C800 + +/* GPIO005: PMIC SSI. (2 << 4) */ +#define IOCG_006_REG (IOCG_REG_BASE + 0x018) + +#define TIMER9_REG_BASE 0xE8A00000 + +#define WDT0_REG_BASE 0xE8A06000 +#define WDT1_REG_BASE 0xE8A07000 +#define WDT_CONTROL_OFFSET 0x008 +#define WDT_LOCK_OFFSET 0xC00 + +#define WDT_UNLOCK 0x1ACCE551 +#define WDT_LOCKED 1 + +#define PCTRL_REG_BASE 0xE8A09000 +#define PCTRL_PERI_CTRL3_REG (PCTRL_REG_BASE + 0x010) +#define PCTRL_PERI_CTRL24_REG (PCTRL_REG_BASE + 0x064) + +#define GPIO0_BASE UL(0xE8A0B000) +#define GPIO1_BASE UL(0xE8A0C000) +#define GPIO2_BASE UL(0xE8A0D000) +#define GPIO3_BASE UL(0xE8A0E000) +#define GPIO4_BASE UL(0xE8A0F000) +#define GPIO5_BASE UL(0xE8A10000) +#define GPIO6_BASE UL(0xE8A11000) +#define GPIO7_BASE UL(0xE8A12000) +#define GPIO8_BASE UL(0xE8A13000) +#define GPIO9_BASE UL(0xE8A14000) +#define GPIO10_BASE UL(0xE8A15000) +#define GPIO11_BASE UL(0xE8A16000) +#define GPIO12_BASE UL(0xE8A17000) +#define GPIO13_BASE UL(0xE8A18000) +#define GPIO14_BASE UL(0xE8A19000) +#define GPIO15_BASE UL(0xE8A1A000) +#define GPIO16_BASE UL(0xE8A1B000) +#define GPIO17_BASE UL(0xE8A1C000) +#define GPIO20_BASE UL(0xE8A1F000) +#define GPIO21_BASE UL(0xE8A20000) +#define GPIO22_BASE UL(0xFFF0B000) +#define GPIO23_BASE UL(0xFFF0C000) +#define GPIO24_BASE UL(0xFFF0D000) +#define GPIO25_BASE UL(0xFFF0E000) +#define GPIO26_BASE UL(0xFFF0F000) +#define GPIO27_BASE UL(0xFFF10000) +#define GPIO28_BASE UL(0xFFF1D000) + +#define TZC_REG_BASE 0xE8A21000 +#define TZC_STAT0_REG (TZC_REG_BASE + 0x800) +#define TZC_EN0_REG (TZC_REG_BASE + 0x804) +#define TZC_DIS0_REG (TZC_REG_BASE + 0x808) +#define TZC_STAT1_REG (TZC_REG_BASE + 0x80C) +#define TZC_EN1_REG (TZC_REG_BASE + 0x810) +#define TZC_DIS1_REG (TZC_REG_BASE + 0x814) +#define TZC_STAT2_REG (TZC_REG_BASE + 0x818) +#define TZC_EN2_REG (TZC_REG_BASE + 0x81C) +#define TZC_DIS2_REG (TZC_REG_BASE + 0x820) +#define TZC_STAT3_REG (TZC_REG_BASE + 0x824) +#define TZC_EN3_REG (TZC_REG_BASE + 0x828) +#define TZC_DIS3_REG (TZC_REG_BASE + 0x82C) +#define TZC_STAT4_REG (TZC_REG_BASE + 0x830) +#define TZC_EN4_REG (TZC_REG_BASE + 0x834) +#define TZC_DIS4_REG (TZC_REG_BASE + 0x838) +#define TZC_STAT5_REG (TZC_REG_BASE + 0x83C) +#define TZC_EN5_REG (TZC_REG_BASE + 0x840) +#define TZC_DIS5_REG (TZC_REG_BASE + 0x844) +#define TZC_STAT6_REG (TZC_REG_BASE + 0x848) +#define TZC_EN6_REG (TZC_REG_BASE + 0x84C) +#define TZC_DIS6_REG (TZC_REG_BASE + 0x850) +#define TZC_STAT7_REG (TZC_REG_BASE + 0x854) +#define TZC_EN7_REG (TZC_REG_BASE + 0x858) +#define TZC_DIS7_REG (TZC_REG_BASE + 0x85C) +#define TZC_STAT8_REG (TZC_REG_BASE + 0x860) +#define TZC_EN8_REG (TZC_REG_BASE + 0x864) +#define TZC_DIS8_REG (TZC_REG_BASE + 0x868) + +#define MMBUF_BASE 0xEA800000 + +#define ACPU_DMCPACK0_BASE 0xEA900000 + +#define ACPU_DMCPACK1_BASE 0xEA920000 + +#define ACPU_DMCPACK2_BASE 0xEA940000 + +#define ACPU_DMCPACK3_BASE 0xEA960000 + +#define UART5_REG_BASE 0xFDF05000 + +#define USB3OTG_REG_BASE 0xFF100000 + +#define UFS_REG_BASE 0xFF3B0000 + +#define UFS_SYS_REG_BASE 0xFF3B1000 + +#define UFS_SYS_PSW_POWER_CTRL_REG (UFS_SYS_REG_BASE + 0x004) +#define UFS_SYS_PHY_ISO_EN_REG (UFS_SYS_REG_BASE + 0x008) +#define UFS_SYS_HC_LP_CTRL_REG (UFS_SYS_REG_BASE + 0x00C) +#define UFS_SYS_PHY_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x010) +#define UFS_SYS_PSW_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x014) +#define UFS_SYS_CLOCK_GATE_BYPASS_REG (UFS_SYS_REG_BASE + 0x018) +#define UFS_SYS_RESET_CTRL_EN_REG (UFS_SYS_REG_BASE + 0x01C) +#define UFS_SYS_MONITOR_HH_REG (UFS_SYS_REG_BASE + 0x03C) +#define UFS_SYS_UFS_SYSCTRL_REG (UFS_SYS_REG_BASE + 0x05C) +#define UFS_SYS_UFS_DEVICE_RESET_CTRL_REG (UFS_SYS_REG_BASE + 0x060) +#define UFS_SYS_UFS_APB_ADDR_MASK_REG (UFS_SYS_REG_BASE + 0x064) + +#define BIT_UFS_PSW_ISO_CTRL (1 << 16) +#define BIT_UFS_PSW_MTCMOS_EN (1 << 0) +#define BIT_UFS_REFCLK_ISO_EN (1 << 16) +#define BIT_UFS_PHY_ISO_CTRL (1 << 0) +#define BIT_SYSCTRL_LP_ISOL_EN (1 << 16) +#define BIT_SYSCTRL_PWR_READY (1 << 8) +#define BIT_SYSCTRL_REF_CLOCK_EN (1 << 24) +#define MASK_SYSCTRL_REF_CLOCK_SEL (3 << 8) +#define MASK_SYSCTRL_CFG_CLOCK_FREQ (0xFF) +#define BIT_SYSCTRL_PSW_CLK_EN (1 << 4) +#define MASK_UFS_CLK_GATE_BYPASS (0x3F) +#define BIT_SYSCTRL_LP_RESET_N (1 << 0) +#define BIT_UFS_REFCLK_SRC_SE1 (1 << 0) +#define MASK_UFS_SYSCTRL_BYPASS (0x3F << 16) +#define MASK_UFS_DEVICE_RESET (1 << 16) +#define BIT_UFS_DEVICE_RESET (1 << 0) + +#define GPIO18_BASE UL(0xFF3B4000) +#define GPIO19_BASE UL(0xFF3B5000) + +#define IOMG_FIX_REG_BASE 0xFF3B6000 + +/* GPIO150: LED */ +#define IOMG_FIX_006_REG (IOMG_FIX_REG_BASE + 0x018) +/* GPIO151: LED */ +#define IOMG_FIX_007_REG (IOMG_FIX_REG_BASE + 0x01C) + +#define IOMG_AO_REG_BASE 0xFFF11000 + +/* GPIO189: LED */ +#define IOMG_AO_011_REG (IOMG_AO_REG_BASE + 0x02C) +/* GPIO190: LED */ +#define IOMG_AO_012_REG (IOMG_AO_REG_BASE + 0x030) +/* GPIO202: type C enable. active low */ +#define IOMG_AO_023_REG (IOMG_AO_REG_BASE + 0x05C) +/* GPIO206: USB switch. active low */ +#define IOMG_AO_026_REG (IOMG_AO_REG_BASE + 0x068) +/* GPIO219: PD interrupt. pull up */ +#define IOMG_AO_039_REG (IOMG_AO_REG_BASE + 0x09C) +/* GPIO213: PCIE_CLKREQ_N */ +#define IOMG_AO_033_REG (IOMG_AO_REG_BASE + 0x084) + +#define IOCG_AO_REG_BASE 0xFFF1187C +/* GPIO219: PD interrupt. pull up */ +#define IOCG_AO_043_REG (IOCG_AO_REG_BASE + 0x030) + +#define EDMAC_BASE 0xfdf30000 +#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694) +#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6)) +#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1) +#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0) +#define EDMAC_CHANNEL_NUMS 16 + +#define IOMCU_DMAC_BASE 0xffd77000 +#define IOMCU_DMAC_SEC_CTRL (IOMCU_DMAC_BASE + 0x694) +#define IOMCU_DMAC_AXI_CONF(x) (IOMCU_DMAC_BASE + 0x820 + ((x) << 6)) +#define IOMCU_DMAC_AXI_CONF_ARPROT_NS (1 << 6) +#define IOMCU_DMAC_AXI_CONF_AWPROT_NS (1 << 18) +#define IOMCU_DMAC_SEC_CTRL_INTR_SEC (1 << 1) +#define IOMCU_DMAC_SEC_CTRL_GLOBAL_SEC (1 << 0) +#define IOMCU_DMAC_CHANNEL_NUMS 8 + +#endif /* HI3660_H */ diff --git a/plat/hisilicon/hikey960/include/hi3660_crg.h b/plat/hisilicon/hikey960/include/hi3660_crg.h new file mode 100644 index 0000000..eb5a6c5 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660_crg.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef HI3660_CRG_H +#define HI3660_CRG_H + +#define CRG_REG_BASE 0xFFF35000 + +#define CRG_PEREN0_REG (CRG_REG_BASE + 0x000) +#define CRG_PERDIS0_REG (CRG_REG_BASE + 0x004) +#define CRG_PERSTAT0_REG (CRG_REG_BASE + 0x008) +#define PEREN0_GT_CLK_AOMM (1U << 31) + +#define CRG_PEREN1_REG (CRG_REG_BASE + 0x010) +#define CRG_PERDIS1_REG (CRG_REG_BASE + 0x014) +#define CRG_PERSTAT1_REG (CRG_REG_BASE + 0x018) +#define CRG_PEREN2_REG (CRG_REG_BASE + 0x020) +#define CRG_PERDIS2_REG (CRG_REG_BASE + 0x024) +#define CRG_PERSTAT2_REG (CRG_REG_BASE + 0x028) +#define PEREN2_HKADCSSI (1 << 24) + +#define CRG_PEREN3_REG (CRG_REG_BASE + 0x030) +#define CRG_PERDIS3_REG (CRG_REG_BASE + 0x034) + +#define CRG_PEREN4_REG (CRG_REG_BASE + 0x040) +#define CRG_PERDIS4_REG (CRG_REG_BASE + 0x044) +#define CRG_PERCLKEN4_REG (CRG_REG_BASE + 0x048) +#define CRG_PERSTAT4_REG (CRG_REG_BASE + 0x04C) +#define GT_ACLK_USB3OTG (1 << 1) +#define GT_CLK_USB3OTG_REF (1 << 0) + +#define CRG_PEREN5_REG (CRG_REG_BASE + 0x050) +#define CRG_PERDIS5_REG (CRG_REG_BASE + 0x054) +#define CRG_PERSTAT5_REG (CRG_REG_BASE + 0x058) +#define CRG_PERRSTEN0_REG (CRG_REG_BASE + 0x060) +#define CRG_PERRSTDIS0_REG (CRG_REG_BASE + 0x064) +#define CRG_PERRSTSTAT0_REG (CRG_REG_BASE + 0x068) +#define CRG_PERRSTEN1_REG (CRG_REG_BASE + 0x06C) +#define CRG_PERRSTDIS1_REG (CRG_REG_BASE + 0x070) +#define CRG_PERRSTSTAT1_REG (CRG_REG_BASE + 0x074) +#define CRG_PERRSTEN2_REG (CRG_REG_BASE + 0x078) +#define CRG_PERRSTDIS2_REG (CRG_REG_BASE + 0x07C) +#define CRG_PERRSTSTAT2_REG (CRG_REG_BASE + 0x080) +#define PERRSTEN2_HKADCSSI (1 << 24) + +#define CRG_PERRSTEN3_REG (CRG_REG_BASE + 0x084) +#define CRG_PERRSTDIS3_REG (CRG_REG_BASE + 0x088) +#define CRG_PERRSTSTAT3_REG (CRG_REG_BASE + 0x08C) +#define CRG_PERRSTEN4_REG (CRG_REG_BASE + 0x090) +#define CRG_PERRSTDIS4_REG (CRG_REG_BASE + 0x094) +#define CRG_PERRSTSTAT4_REG (CRG_REG_BASE + 0x098) +#define IP_RST_USB3OTG_MUX (1 << 8) +#define IP_RST_USB3OTG_AHBIF (1 << 7) +#define IP_RST_USB3OTG_32K (1 << 6) +#define IP_RST_USB3OTG (1 << 5) +#define IP_RST_USB3OTGPHY_POR (1 << 3) + +#define CRG_PERRSTEN5_REG (CRG_REG_BASE + 0x09C) +#define CRG_PERRSTDIS5_REG (CRG_REG_BASE + 0x0A0) +#define CRG_PERRSTSTAT5_REG (CRG_REG_BASE + 0x0A4) + +/* bit fields in CRG_PERI */ +#define PERI_PCLK_PCTRL_BIT (1U << 31) +#define PERI_TIMER12_BIT (1 << 25) +#define PERI_TIMER11_BIT (1 << 24) +#define PERI_TIMER10_BIT (1 << 23) +#define PERI_TIMER9_BIT (1 << 22) +#define PERI_UART5_BIT (1 << 15) +#define PERI_UFS_BIT (1 << 12) +#define PERI_ARST_UFS_BIT (1 << 7) +#define PERI_PPLL2_EN_CPU (1 << 3) +#define PERI_PWM_BIT (1 << 0) +#define PERI_DDRC_BIT (1 << 0) +#define PERI_DDRC_D_BIT (1 << 4) +#define PERI_DDRC_C_BIT (1 << 3) +#define PERI_DDRC_B_BIT (1 << 2) +#define PERI_DDRC_A_BIT (1 << 1) +#define PERI_DDRC_DMUX_BIT (1 << 0) + +#define CRG_CLKDIV0_REG (CRG_REG_BASE + 0x0A0) +#define SC_DIV_LPMCU_MASK ((0x1F << 5) << 16) +#define SC_DIV_LPMCU(x) (((x) & 0x1F) << 5) + +#define CRG_CLKDIV1_REG (CRG_REG_BASE + 0x0B0) +#define SEL_LPMCU_PLL_MASK ((1 << 1) << 16) +#define SEL_SYSBUS_MASK ((1 << 0) << 16) +#define SEL_LPMCU_PLL1 (1 << 1) +#define SEL_LPMCU_PLL0 (0 << 1) +#define SEL_SYSBUS_PLL0 (1 << 0) +#define SEL_SYSBUS_PLL1 (0 << 0) + +#define CRG_CLKDIV3_REG (CRG_REG_BASE + 0x0B4) +#define CRG_CLKDIV5_REG (CRG_REG_BASE + 0x0BC) +#define CRG_CLKDIV8_REG (CRG_REG_BASE + 0x0C8) + +#define CRG_CLKDIV12_REG (CRG_REG_BASE + 0x0D8) +#define SC_DIV_A53HPM_MASK (0x7 << 13) +#define SC_DIV_A53HPM(x) (((x) & 0x7) << 13) + +#define CRG_CLKDIV16_REG (CRG_REG_BASE + 0x0E8) +#define DDRC_CLK_SW_REQ_CFG_MASK (0x3 << 12) +#define DDRC_CLK_SW_REQ_CFG(x) (((x) & 0x3) << 12) +#define SC_DIV_UFSPHY_CFG_MASK (0x3 << 9) +#define SC_DIV_UFSPHY_CFG(x) (((x) & 0x3) << 9) +#define DDRCPLL_SW (1 << 8) + +#define CRG_CLKDIV17_REG (CRG_REG_BASE + 0x0EC) +#define SC_DIV_UFS_PERIBUS (1 << 14) + +#define CRG_CLKDIV18_REG (CRG_REG_BASE + 0x0F0) +#define CRG_CLKDIV19_REG (CRG_REG_BASE + 0x0F4) +#define CRG_CLKDIV20_REG (CRG_REG_BASE + 0x0F8) +#define CLKDIV20_GT_CLK_AOMM (1 << 3) + +#define CRG_CLKDIV22_REG (CRG_REG_BASE + 0x100) +#define SEL_PLL_320M_MASK (1 << 16) +#define SEL_PLL2_320M (1 << 0) +#define SEL_PLL0_320M (0 << 0) + +#define CRG_CLKDIV23_REG (CRG_REG_BASE + 0x104) +#define PERI_DDRC_SW_BIT (1 << 13) +#define DIV_CLK_DDRSYS_MASK (0x3 << 10) +#define DIV_CLK_DDRSYS(x) (((x) & 0x3) << 10) +#define GET_DIV_CLK_DDRSYS(x) (((x) & DIV_CLK_DDRSYS_MASK) >> 10) +#define DIV_CLK_DDRCFG_MASK (0x6 << 5) +#define DIV_CLK_DDRCFG(x) (((x) & 0x6) << 5) +#define GET_DIV_CLK_DDRCFG(x) (((x) & DIV_CLK_DDRCFG_MASK) >> 5) +#define DIV_CLK_DDRC_MASK 0x1F +#define DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK) +#define GET_DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK) + +#define CRG_CLKDIV25_REG (CRG_REG_BASE + 0x10C) +#define DIV_SYSBUS_PLL_MASK (0xF << 16) +#define DIV_SYSBUS_PLL(x) ((x) & 0xF) + +#define CRG_PERI_CTRL2_REG (CRG_REG_BASE + 0x128) +#define PERI_TIME_STAMP_CLK_MASK (0x7 << 28) +#define PERI_TIME_STAMP_CLK_DIV(x) (((x) & 0x7) << 22) + +#define CRG_ISODIS_REG (CRG_REG_BASE + 0x148) +#define CRG_PERPWREN_REG (CRG_REG_BASE + 0x150) + +#define CRG_PEREN7_REG (CRG_REG_BASE + 0x420) +#define CRG_PERDIS7_REG (CRG_REG_BASE + 0x424) +#define CRG_PERSTAT7_REG (CRG_REG_BASE + 0x428) +#define GT_CLK_UFSPHY_CFG (1 << 14) + +#define CRG_PEREN8_REG (CRG_REG_BASE + 0x430) +#define CRG_PERDIS8_REG (CRG_REG_BASE + 0x434) +#define CRG_PERSTAT8_REG (CRG_REG_BASE + 0x438) +#define PERI_DMC_D_BIT (1 << 22) +#define PERI_DMC_C_BIT (1 << 21) +#define PERI_DMC_B_BIT (1 << 20) +#define PERI_DMC_A_BIT (1 << 19) +#define PERI_DMC_BIT (1 << 18) + +#define CRG_PEREN11_REG (CRG_REG_BASE + 0x460) +#define PPLL1_GATE_CPU (1 << 18) + +#define CRG_PERSTAT11_REG (CRG_REG_BASE + 0x46C) +#define PPLL3_EN_STAT (1 << 21) +#define PPLL2_EN_STAT (1 << 20) +#define PPLL1_EN_STAT (1 << 19) + +#define CRG_IVP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC04) +#define CRG_ISP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC84) + +#define CRG_RVBAR(c, n) (0xE00 + (0x10 * c) + (0x4 * n)) +#define CRG_GENERAL_SEC_RSTEN_REG (CRG_REG_BASE + 0xE20) +#define CRG_GENERAL_SEC_RSTDIS_REG (CRG_REG_BASE + 0xE24) +#define IP_RST_GPIO0_SEC (1 << 2) + +#define CRG_GENERAL_SEC_CLKDIV0_REG (CRG_REG_BASE + 0xE90) +#define SC_DIV_AO_HISE_MASK 3 +#define SC_DIV_AO_HISE(x) ((x) & 0x3) + +#endif /* HI3660_CRG_H */ diff --git a/plat/hisilicon/hikey960/include/hi3660_hkadc.h b/plat/hisilicon/hikey960/include/hi3660_hkadc.h new file mode 100644 index 0000000..dc9e813 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660_hkadc.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef HI3660_HKADC_H +#define HI3660_HKADC_H + +#define HKADC_SSI_REG_BASE 0xE82B8000 + +#define HKADC_DSP_START_REG (HKADC_SSI_REG_BASE + 0x000) +#define HKADC_WR_NUM_REG (HKADC_SSI_REG_BASE + 0x008) +#define HKADC_DSP_START_CLR_REG (HKADC_SSI_REG_BASE + 0x01C) +#define HKADC_WR01_DATA_REG (HKADC_SSI_REG_BASE + 0x020) + +#define WR1_WRITE_MODE (1U << 31) +#define WR1_READ_MODE (0 << 31) +#define WR1_ADDR(x) (((x) & 0x7F) << 24) +#define WR1_DATA(x) (((x) & 0xFF) << 16) +#define WR0_WRITE_MODE (1 << 15) +#define WR0_READ_MODE (0 << 15) +#define WR0_ADDR(x) (((x) & 0x7F) << 8) +#define WR0_DATA(x) ((x) & 0xFF) + +#define HKADC_WR23_DATA_REG (HKADC_SSI_REG_BASE + 0x024) +#define HKADC_WR45_DATA_REG (HKADC_SSI_REG_BASE + 0x028) +#define HKADC_DELAY01_REG (HKADC_SSI_REG_BASE + 0x030) +#define HKADC_DELAY23_REG (HKADC_SSI_REG_BASE + 0x034) +#define HKADC_DELAY45_REG (HKADC_SSI_REG_BASE + 0x038) +#define HKADC_DSP_RD2_DATA_REG (HKADC_SSI_REG_BASE + 0x048) +#define HKADC_DSP_RD3_DATA_REG (HKADC_SSI_REG_BASE + 0x04C) + +/* HKADC Internal Registers */ +#define HKADC_CTRL_ADDR 0x00 +#define HKADC_START_ADDR 0x01 +#define HKADC_DATA1_ADDR 0x03 /* high 8 bits */ +#define HKADC_DATA0_ADDR 0x04 /* low 8 bits */ +#define HKADC_MODE_CFG 0x0A + +#define HKADC_VALUE_HIGH 0x0FF0 +#define HKADC_VALUE_LOW 0x000F +#define HKADC_VALID_VALUE 0x0FFF + +#define HKADC_CHANNEL_MAX 15 +#define HKADC_VREF_1V8 1800 +#define HKADC_ACCURACY 0x0FFF + +#define HKADC_WR01_VALUE ((HKADC_START_ADDR << 24) | \ + (0x1 << 16)) +#define HKADC_WR23_VALUE ((0x1u << 31) | \ + (HKADC_DATA0_ADDR << 24) | \ + (1 << 15) | \ + (HKADC_DATA1_ADDR << 8)) +#define HKADC_WR45_VALUE (0x80) +#define HKADC_CHANNEL0_DELAY01_VALUE ((0x0700 << 16) | 0xFFFF) +#define HKADC_DELAY01_VALUE ((0x0700 << 16) | 0x0200) +#define HKADC_DELAY23_VALUE ((0x00C8 << 16) | 0x00C8) +#define START_DELAY_TIMEOUT 2000 +#define HKADC_WR_NUM_VALUE 4 + +#endif /* HI3660_HKADC_H */ diff --git a/plat/hisilicon/hikey960/include/hi3660_mem_map.h b/plat/hisilicon/hikey960/include/hi3660_mem_map.h new file mode 100644 index 0000000..cadc4a4 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660_mem_map.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI3660_MEM_MAP_H +#define HI3660_MEM_MAP_H + +#define HISI_DATA_HEAD_BASE (0x89C44400) + +#define HISI_RESERVED_MEM_BASE (0x89C80000) +#define HISI_RESERVED_MEM_SIZE (0x00040000) + +#define HISI_DATA0_BASE (0x89C96180) +#define HISI_DATA0_SIZE (0x000003A0) +#define HISI_DATA1_BASE (0x89C93480) +#define HISI_DATA1_SIZE (0x00002D00) + +#endif /* HI3660_MEM_MAP_H */ diff --git a/plat/hisilicon/hikey960/include/hisi_ipc.h b/plat/hisilicon/hikey960/include/hisi_ipc.h new file mode 100644 index 0000000..6a97968 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hisi_ipc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_IPC_H +#define HISI_IPC_H + +enum pm_mode { + PM_ON = 0, + PM_OFF, +}; + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode); +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level); +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster); +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id); +int hisi_ipc_init(void); + +#endif /* HISI_IPC_H */ diff --git a/plat/hisilicon/hikey960/include/plat.ld.S b/plat/hisilicon/hikey960/include/plat.ld.S new file mode 100644 index 0000000..f8bd376 --- /dev/null +++ b/plat/hisilicon/hikey960/include/plat.ld.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_LD_S +#define PLAT_LD_S + +#include <lib/xlat_tables/xlat_tables_defs.h> + +MEMORY { + RAM2 (rw): ORIGIN = DDR2_SEC_BASE, LENGTH = DDR2_SEC_SIZE +} + +SECTIONS +{ + .ram2_region (NOLOAD) : { + *(.ram2_region) + }>RAM2 +} + +#endif /* PLAT_LD_S */ diff --git a/plat/hisilicon/hikey960/include/plat_macros.S b/plat/hisilicon/hikey960/include/plat_macros.S new file mode 100644 index 0000000..8765562 --- /dev/null +++ b/plat/hisilicon/hikey960/include/plat_macros.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <hi3660.h> +#include <platform_def.h> + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + mov_imm x16, GICD_REG_BASE + mov_imm x17, GICC_REG_BASE + + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + /* Store to the crash buf and print to cosole */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +2: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq 1f + bl asm_print_hex + adr x4, spacer + bl asm_print_str + ldr x4, [x7], #8 + bl asm_print_hex + adr x4, newline + bl asm_print_str + b 2b +1: + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE3_CLUSTER_IX)) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE4_CLUSTER_IX)) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h new file mode 100644 index 0000000..10eff01 --- /dev/null +++ b/plat/hisilicon/hikey960/include/platform_def.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <lib/utils_def.h> + +#include "../hikey960_def.h" + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define HIKEY960_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* + * Generic platform constants + */ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x1000 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_CORE_COUNT_PER_CLUSTER) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + 1) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 +/* UFS RPMB and UFS User Data */ +#define MAX_IO_BLOCK_DEVICES U(2) + + +/* + * Platform memory map related constants + */ + +/* + * BL1 specific defines. + */ +#define BL1_RO_BASE (0x1AC00000) +#define BL1_RO_LIMIT (BL1_RO_BASE + 0x20000) +#define BL1_RW_BASE (BL1_RO_LIMIT) /* 1AC2_0000 */ +#define BL1_RW_SIZE (0x00188000) +#define BL1_RW_LIMIT (0x1B000000) + +/* + * BL2 specific defines. + */ +#define BL2_BASE (0x1AC00000) +#define BL2_LIMIT (BL2_BASE + 0x58000) /* 1AC5_8000 */ + +/* + * BL31 specific defines. + */ +#define BL31_BASE (BL2_LIMIT) /* 1AC5_8000 */ +#define BL31_LIMIT (BL31_BASE + 0x40000) /* 1AC9_8000 */ + +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM. + */ +#define BL32_DRAM_BASE DDR_SEC_BASE +#define BL32_DRAM_LIMIT (DDR_SEC_BASE+DDR_SEC_SIZE) + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define HIKEY960_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */ +#define HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */ +#endif + +#if (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_SRAM_ID) +#error "SRAM storage of TSP payload is currently unsupported" +#else +#error "Currently unsupported HIKEY960_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifdef __aarch64__ +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#define NS_BL1U_BASE (BL31_LIMIT) /* 1AC9_8000 */ +#define NS_BL1U_SIZE (0x00100000) +#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE) + +#define HIKEY960_NS_IMAGE_OFFSET (0x1AC28000) /* offset in l-loader */ +#define HIKEY960_NS_TMP_OFFSET (0x1AE00000) + +#define SCP_BL2_BASE (0x89C80000) +#define SCP_BL2_SIZE (0x00040000) + +/* + * Platform specific page table and MMU setup constants + */ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) +#define MAX_XLAT_TABLES 3 +#endif + +#if defined(IMAGE_BL2) +#define MAX_XLAT_TABLES 5 +#endif + +#if defined(IMAGE_BL31) +#if defined(SPMC_AT_EL3) +#define MAX_XLAT_TABLES 17 +#else +#define MAX_XLAT_TABLES 5 +#endif +#endif + +#define MAX_MMAP_REGIONS 16 + +/* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + */ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk new file mode 100644 index 0000000..fd11a4d --- /dev/null +++ b/plat/hisilicon/hikey960/platform.mk @@ -0,0 +1,182 @@ +# +# Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Non-TF Boot ROM +RESET_TO_BL2 := 1 + +# On Hikey960, the TSP can execute from TZC secure area in DRAM. +HIKEY960_TSP_RAM_LOCATION ?= dram +ifeq (${HIKEY960_TSP_RAM_LOCATION}, dram) + HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_DRAM_ID +else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram) + HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_SRAM_ID +else + $(error "Currently unsupported HIKEY960_TSP_RAM_LOCATION value") +endif + +CRASH_CONSOLE_BASE := PL011_UART6_BASE +COLD_BOOT_SINGLE_CPU := 1 +PLAT_PL061_MAX_GPIOS := 232 +PROGRAMMABLE_RESET_ADDRESS := 1 +ENABLE_SVE_FOR_NS := 0 +PLAT_PARTITION_BLOCK_SIZE := 4096 + +# Process flags +$(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID)) +$(eval $(call add_define,CRASH_CONSOLE_BASE)) +$(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) +$(eval $(call add_define,PLAT_PARTITION_BLOCK_SIZE)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +USE_COHERENT_MEM := 1 + +PLAT_INCLUDES := -Iplat/hisilicon/hikey960/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + plat/hisilicon/hikey960/aarch64/hikey960_common.c \ + plat/hisilicon/hikey960/hikey960_boardid.c + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +HIKEY960_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/synopsys/ufs/dw_ufs.c \ + drivers/ufs/ufs.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl1_setup.c \ + plat/hisilicon/hikey960/hikey960_bl_common.c \ + plat/hisilicon/hikey960/hikey960_io_storage.c \ + ${HIKEY960_GIC_SOURCES} + +BL2_SOURCES += common/desc_image_load.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/synopsys/ufs/dw_ufs.c \ + drivers/ufs/ufs.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c \ + plat/hisilicon/hikey960/hikey960_bl2_setup.c \ + plat/hisilicon/hikey960/hikey960_bl_common.c \ + plat/hisilicon/hikey960/hikey960_image_load.c \ + plat/hisilicon/hikey960/hikey960_io_storage.c \ + plat/hisilicon/hikey960/hikey960_mcu_load.c + +ifeq (${SPD},opteed) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +include lib/zlib/zlib.mk +PLAT_INCLUDES += -Ilib/zlib +BL2_SOURCES += $(ZLIB_SOURCES) + +BL31_SOURCES += drivers/arm/cci/cci.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S \ + plat/common/plat_psci_common.c \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl31_setup.c \ + plat/hisilicon/hikey960/hikey960_bl_common.c \ + plat/hisilicon/hikey960/hikey960_pm.c \ + plat/hisilicon/hikey960/hikey960_topology.c \ + plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \ + plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c \ + ${HIKEY960_GIC_SOURCES} + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + +BL1_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey960/hikey960_tbbr.c \ + plat/hisilicon/hikey960/hikey960_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey960/hikey960_tbbr.c \ + plat/hisilicon/hikey960/hikey960_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(BUILD_PLAT)/bl1/hikey960_rotpk.o: $(ROTPK_HASH) +$(BUILD_PLAT)/bl2/hikey960_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +# Enable workarounds for selected Cortex-A53 errata. +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +FIP_ALIGN := 512 + +# SPM dispatcher +ifeq (${SPD},spmd) +ifeq (${SPMC_AT_EL3},1) +# include device tree helper library +include lib/libfdt/libfdt.mk +BL31_SOURCES += common/fdt_wrappers.c \ + ${LIBFDT_SRCS} \ + common/uuid.c + +# Add support for platform supplied linker script for BL31 build +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) +endif + +ifeq ($(PLAT_SP_MANIFEST_DTS),) + $(error "Error: A SP manifest is required for the SPMC.") +endif +FDT_SOURCES += ${PLAT_SP_MANIFEST_DTS} +endif diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c new file mode 100644 index 0000000..fcd0a8b --- /dev/null +++ b/plat/hisilicon/poplar/aarch64/platform_common.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables.h> +#include <plat/common/platform.h> + +#include "hi3798cv200.h" +#include "platform_def.h" + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#ifdef SPD_opteed +#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \ + POPLAR_OPTEE_PAGEABLE_LOAD_BASE, \ + POPLAR_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +static const mmap_region_t poplar_mmap[] = { + MAP_DDR, + MAP_DEVICE, + MAP_TSP_MEM, +#ifdef SPD_opteed + MAP_OPTEE_PAGEABLE, +#endif + {0} +}; + +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void plat_configure_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(poplar_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +DEFINE_CONFIGURE_MMU_EL(3) +DEFINE_CONFIGURE_MMU_EL(1) + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/plat/hisilicon/poplar/aarch64/poplar_helpers.S new file mode 100644 index 0000000..063ee64 --- /dev/null +++ b/plat/hisilicon/poplar/aarch64/poplar_helpers.S @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_my_core_pos + .globl poplar_calc_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses poplar_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b poplar_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int poplar_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func poplar_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc poplar_calc_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, POPLAR_CRASH_UART_BASE + mov_imm x1, POPLAR_CRASH_UART_CLK_IN_HZ + mov_imm x2, POPLAR_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, POPLAR_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : r0 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, POPLAR_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on ARM + * platforms. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c new file mode 100644 index 0000000..acc1f0e --- /dev/null +++ b/plat/hisilicon/poplar/bl1_plat_setup.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/arm/pl011.h> +#include <drivers/arm/pl061_gpio.h> +#include <drivers/generic_delay_timer.h> +#include <drivers/mmc.h> +#include <drivers/synopsys/dw_mmc.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include "hi3798cv200.h" +#include "plat_private.h" + +/* Data structure which holds the extents of the trusted RAM for BL1 */ +static meminfo_t bl1_tzram_layout; +static meminfo_t bl2_tzram_layout; +static console_t console; + +#if !POPLAR_RECOVERY +static struct mmc_device_info mmc_info; +#endif + +/* + * Cannot use default weak implementation in bl1_main.c because BL1 RW data is + * not at the top of the secure memory. + */ +int bl1_plat_handle_post_image_load(unsigned int image_id) +{ + image_desc_t *image_desc; + entry_point_info_t *ep_info; + + if (image_id != BL2_IMAGE_ID) + return 0; + + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(image_desc != NULL); + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; + + bl2_tzram_layout.total_base = BL2_BASE; + bl2_tzram_layout.total_size = BL32_LIMIT - BL2_BASE; + + flush_dcache_range((uintptr_t)&bl2_tzram_layout, sizeof(meminfo_t)); + + ep_info->args.arg1 = (uintptr_t)&bl2_tzram_layout; + + VERBOSE("BL1: BL2 memory layout address = %p\n", + (void *)&bl2_tzram_layout); + + return 0; +} + +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL1_RW_BASE; + bl1_tzram_layout.total_size = BL1_RW_SIZE; + + INFO("BL1: 0x%lx - 0x%lx [size = %zu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + BL1_RAM_LIMIT - BL1_RAM_BASE); +} + +void bl1_plat_arch_setup(void) +{ + plat_configure_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL1_RO_BASE, /* l-loader and BL1 ROM */ + BL1_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl1_platform_setup(void) +{ + int i; +#if !POPLAR_RECOVERY + dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE); +#endif + + generic_delay_timer_init(); + + pl061_gpio_init(); + for (i = 0; i < GPIO_MAX; i++) + pl061_gpio_register(GPIO_BASE(i), i); + +#if !POPLAR_RECOVERY + /* SoC-specific emmc register are initialized/configured by bootrom */ + INFO("BL1: initializing emmc\n"); + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); +#endif + + plat_io_setup(); +} + +unsigned int bl1_plat_get_next_image_id(void) +{ + return BL2_IMAGE_ID; +} diff --git a/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c b/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..9bda02e --- /dev/null +++ b/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + +#else /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = POPLAR_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager + * image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged + * image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = POPLAR_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = POPLAR_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = PLAT_POPLAR_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_POPLAR_NS_IMAGE_OFFSET, + .image_info.image_max_size = DDR_BASE + DDR_SIZE - + PLAT_POPLAR_NS_IMAGE_OFFSET, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c new file mode 100644 index 0000000..ee46772 --- /dev/null +++ b/plat/hisilicon/poplar/bl2_plat_setup.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/arm/pl011.h> +#include <drivers/generic_delay_timer.h> +#include <drivers/partition/partition.h> +#include <drivers/synopsys/dw_mmc.h> +#include <drivers/mmc.h> +#include <lib/mmio.h> +#include <lib/optee_utils.h> +#include <plat/common/platform.h> + +#include "hi3798cv200.h" +#include "plat_private.h" + +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); +static console_t console; +#if !POPLAR_RECOVERY +static struct mmc_device_info mmc_info; +#endif + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_poplar_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + /* + * This platform has no SCP_BL2 yet + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t poplar_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t poplar_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +uint32_t poplar_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +int poplar_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + + assert(bl_mem_params); + + switch (image_id) { +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } + + /* + * OP-TEE expect to receive DTB address in x2. + * This will be copied into x2 by dispatcher. + * Set this (arg3) if necessary + */ + /* bl_mem_params->ep_info.args.arg3 = PLAT_HIKEY_DT_BASE; */ +#endif + bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_poplar_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return poplar_bl2_handle_post_image_load(image_id); +} + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct meminfo *mem_layout = (struct meminfo *)arg1; +#if !POPLAR_RECOVERY + dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE); +#endif + + console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Enable arch timer */ + generic_delay_timer_init(); + + bl2_tzram_layout = *mem_layout; + +#if !POPLAR_RECOVERY + /* SoC-specific emmc register are initialized/configured by bootrom */ + INFO("BL2: initializing emmc\n"); + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); +#endif + + plat_io_setup(); +} + +void bl2_plat_arch_setup(void) +{ + plat_configure_mmu_el1(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl2_platform_setup(void) +{ +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_POPLAR_NS_IMAGE_OFFSET; +#endif +} diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c new file mode 100644 index 0000000..fe60ddc --- /dev/null +++ b/plat/hisilicon/poplar/bl31_plat_setup.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <bl31/bl31.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <cortex_a53.h> +#include <drivers/arm/pl011.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include "hi3798cv200.h" +#include "plat_private.h" + +#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45) + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +static console_t console; + +static void hisi_tzpc_sec_init(void) +{ + mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, so + * we are guaranteed to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + void *from_bl2; + + from_bl2 = (void *) arg0; + + console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Init console for crash report */ + plat_crash_console_init(); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_image_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) + panic(); +} + +void bl31_platform_setup(void) +{ + /* Init arch timer */ + generic_delay_timer_init(); + + /* Init GIC distributor and CPU interface */ + poplar_gic_driver_init(); + poplar_gic_init(); + + /* Init security properties of IP blocks */ + hisi_tzpc_sec_init(); +} + +void bl31_plat_runtime_setup(void) +{ + /* do nothing */ +} + +void bl31_plat_arch_setup(void) +{ + plat_configure_mmu_el3(BL31_BASE, + (BL31_LIMIT - BL31_BASE), + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); + + INFO("Boot BL33 from 0x%lx for %" PRIu64 " Bytes\n", + bl33_image_ep_info.pc, bl33_image_ep_info.args.arg2); +} diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h new file mode 100644 index 0000000..e31f4b3 --- /dev/null +++ b/plat/hisilicon/poplar/include/hi3798cv200.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI3798CV200_H +#define HI3798CV200_H + +#include <lib/utils_def.h> + +/* PL011 */ +#define PL011_UART0_BASE (0xF8B00000) +#define PL011_BAUDRATE (115200) +#define PL011_UART0_CLK_IN_HZ (75000000) + +/* Sys Counter */ +#define SYS_COUNTER_FREQ_IN_TICKS (24000000) +#define SYS_COUNTER_FREQ_IN_MHZ (24) + +/* Timer */ +#define SEC_TIMER0_BASE (0xF8008000) +#define TIMER00_LOAD (SEC_TIMER0_BASE + 0x000) +#define TIMER00_VALUE (SEC_TIMER0_BASE + 0x004) +#define TIMER00_CONTROL (SEC_TIMER0_BASE + 0x008) +#define TIMER00_BGLOAD (SEC_TIMER0_BASE + 0x018) + +#define SEC_TIMER2_BASE (0xF8009000) +#define TIMER20_LOAD (SEC_TIMER2_BASE + 0x000) +#define TIMER20_VALUE (SEC_TIMER2_BASE + 0x004) +#define TIMER20_CONTROL (SEC_TIMER2_BASE + 0x008) +#define TIMER20_BGLOAD (SEC_TIMER2_BASE + 0x018) + +/* GPIO */ +#define GPIO_MAX (13) +#define GPIO_BASE(x) (x != 5 ? \ + 0xf820000 + x * 0x1000 : 0xf8004000) + +/* SCTL */ +#define REG_BASE_SCTL (0xF8000000) +#define REG_SC_GEN12 (0x00B0) + +/* CRG */ +#define REG_BASE_CRG (0xF8A22000) +#define REG_CPU_LP (0x48) +#define REG_CPU_RST (0x50) +#define REG_PERI_CRG39 (0x9C) +#define REG_PERI_CRG40 (0xA0) + +/* MCI */ +#define REG_BASE_MCI (0xF9830000) +#define MCI_CDETECT (0x50) +#define MCI_VERID (0x6C) +#define MCI_VERID_VALUE (0x5342250A) +#define MCI_VERID_VALUE2 (0x5342270A) + +/* EMMC */ +#define REG_EMMC_PERI_CRG REG_PERI_CRG40 +#define REG_SDCARD_PERI_CRG REG_PERI_CRG39 +#define EMMC_CLK_MASK (0x7 << 8) +#define EMMC_SRST_REQ (0x1 << 4) +#define EMMC_CKEN (0x1 << 1) +#define EMMC_BUS_CKEN (0x1 << 0) +#define EMMC_CLK_100M (0 << 8) +#define EMMC_CLK_50M (1 << 8) +#define EMMC_CLK_25M (2 << 8) + +#define EMMC_DESC_SIZE U(0x00100000) /* 1MB */ +#define EMMC_INIT_PARAMS(base) \ + { .bus_width = MMC_BUS_WIDTH_8, \ + .clk_rate = 25 * 1000 * 1000, \ + .desc_base = (base), \ + .desc_size = EMMC_DESC_SIZE, \ + .flags = MMC_FLAG_CMD23, \ + .reg_base = REG_BASE_MCI, \ + } + +/* GIC-400 */ +#define GICD_BASE (0xF1001000) +#define GICC_BASE (0xF1002000) +#define GICR_BASE (0xF1000000) + +/* FIQ platform related define */ +#define HISI_IRQ_SEC_SGI_0 8 +#define HISI_IRQ_SEC_SGI_1 9 +#define HISI_IRQ_SEC_SGI_2 10 +#define HISI_IRQ_SEC_SGI_3 11 +#define HISI_IRQ_SEC_SGI_4 12 +#define HISI_IRQ_SEC_SGI_5 13 +#define HISI_IRQ_SEC_SGI_6 14 +#define HISI_IRQ_SEC_SGI_7 15 +#define HISI_IRQ_SEC_PPI_0 29 +#define HISI_IRQ_SEC_TIMER0 60 +#define HISI_IRQ_SEC_TIMER1 50 +#define HISI_IRQ_SEC_TIMER2 52 +#define HISI_IRQ_SEC_TIMER3 88 +#define HISI_IRQ_SEC_AXI 110 + +/* Watchdog */ +#define HISI_WDG0_BASE (0xF8A2C000) + +#define HISI_TZPC_BASE (0xF8A80000) +#define HISI_TZPC_SEC_ATTR_CTRL (HISI_TZPC_BASE + 0x10) + +#endif /* HI3798CV200_H */ diff --git a/plat/hisilicon/poplar/include/plat_macros.S b/plat/hisilicon/poplar/include/plat_macros.S new file mode 100644 index 0000000..82d10c1 --- /dev/null +++ b/plat/hisilicon/poplar/include/plat_macros.S @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +.section .rodata.gic_reg_name, "aS" + .macro plat_crash_print_regs + nop + .endm diff --git a/plat/hisilicon/poplar/include/plat_private.h b/plat/hisilicon/poplar/include/plat_private.h new file mode 100644 index 0000000..a34f138 --- /dev/null +++ b/plat/hisilicon/poplar/include/plat_private.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include <common/bl_common.h> + +#include "hi3798cv200.h" + +void plat_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void plat_configure_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void plat_io_setup(void); + +unsigned int poplar_calc_core_pos(u_register_t mpidr); + +void poplar_gic_driver_init(void); +void poplar_gic_init(void); +void poplar_gic_cpuif_enable(void); +void poplar_gic_pcpu_init(void); + +#endif /* PLAT_PRIVATE_H */ diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h new file mode 100644 index 0000000..ce0fbbc --- /dev/null +++ b/plat/hisilicon/poplar/include/platform_def.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <common/interrupt_props.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/arm/gic_common.h> +#include <lib/utils_def.h> +#include <plat/common/common_def.h> + +#include "hi3798cv200.h" +#include "poplar_layout.h" /* BL memory region sizes, etc */ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define POPLAR_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define POPLAR_CRASH_UART_BASE PL011_UART0_BASE +#define POPLAR_CRASH_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ +#define POPLAR_CONSOLE_BAUDRATE PL011_BAUDRATE + +/* Generic platform constants */ +#define PLATFORM_STACK_SIZE (0x800) + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" +#define BOOT_EMMC_NAME "l-loader.bin" + +#define PLATFORM_CACHE_LINE_SIZE (64) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CORE_COUNT U(4) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) + +/* IO framework user */ +#define MAX_IO_DEVICES (4) +#define MAX_IO_HANDLES (4) +#define MAX_IO_BLOCK_DEVICES U(2) + +/* Memory size options */ +#define POPLAR_DRAM_SIZE_1G 0 +#define POPLAR_DRAM_SIZE_2G 1 + +/* Memory map related constants */ +#define DDR_BASE (0x00000000) + +#if (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_2G) +#define DDR_SIZE (0x80000000) +#elif (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_1G) +#define DDR_SIZE (0x40000000) +#else +#error "Currently unsupported POPLAR_DRAM_SIZE_ID value" +#endif + +#define DEVICE_BASE (0xF0000000) +#define DEVICE_SIZE (0x0F000000) + +#define TEE_SEC_MEM_BASE (0x70000000) +#define TEE_SEC_MEM_SIZE (0x10000000) + +/* Memory location options for TSP */ +#define POPLAR_SRAM_ID 0 +#define POPLAR_DRAM_ID 1 + +/* + * DDR for OP-TEE (26MB from 0x02400000 -0x04000000) is divided in several + * regions: + * - Secure DDR (default is the top 16MB) used by OP-TEE + * - Non-secure DDR (4MB) reserved for OP-TEE's future use + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + */ +#define DDR_SEC_SIZE 0x01000000 +#define DDR_SEC_BASE 0x03000000 + +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM. + */ +#define BL32_DRAM_BASE 0x03000000 +#define BL32_DRAM_LIMIT 0x04000000 + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define POPLAR_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */ +#define POPLAR_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - POPLAR_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x03C0_0000 */ +#endif + +#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID) +#error "SRAM storage of TSP payload is currently unsupported" +#else +#error "Currently unsupported POPLAR_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifdef __aarch64__ +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#define POPLAR_EMMC_DATA_BASE U(0x02200000) +#define POPLAR_EMMC_DATA_SIZE EMMC_DESC_SIZE +#define POPLAR_EMMC_DESC_BASE (POPLAR_EMMC_DATA_BASE + POPLAR_EMMC_DATA_SIZE) +#define POPLAR_EMMC_DESC_SIZE EMMC_DESC_SIZE + +#define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000 + +/* Page table and MMU setup constants */ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES (4) +#define MAX_MMAP_REGIONS (16) + +#define CACHE_WRITEBACK_SHIFT (6) +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* Power states */ +#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL1) +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +/* Interrupt controller */ +#define POPLAR_GICD_BASE GICD_BASE +#define POPLAR_GICC_BASE GICC_BASE + +#define POPLAR_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_AXI, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define POPLAR_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h new file mode 100644 index 0000000..03047f9 --- /dev/null +++ b/plat/hisilicon/poplar/include/poplar_layout.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POPLAR_LAYOUT_H +#define POPLAR_LAYOUT_H + +/* + * Boot memory layout definitions for the HiSilicon Poplar board + */ + +/* + * When Poplar is powered on, boot ROM verifies the initial content of + * boot media, loads it into low memory, and begins executing it + * in 32-bit mode. The image loaded is "l-loader.bin", which contains + * a small amount code along with an embedded ARM Trusted Firmware + * BL1 image. The main purpose of "l-loader" is to prepare the + * processor to execute the BL1 image in 64-bit mode, and to trigger + * that execution. + * + * Also embedded in "l-loader.bin" is a FIP image that contains + * other ARM Trusted Firmware images: BL2; BL31; and for BL33, + * U-Boot. When BL1 executes, it unpacks the BL2 image from the FIP + * image into a region of memory set aside to hold it. Similarly, + * BL2 unpacks BL31 into memory reserved for it, and unpacks U-Boot + * into high memory. + * + * Because the BL1 code is embedded in "l-loader", its base address + * in memory is derived from the base address of the "l-loader" + * text section, together with an offset. Memory space for BL2 is + * reserved immediately following BL1, and memory space is reserved + * for BL31 after that. ARM Trusted Firmware requires each of these + * memory regions to be aligned on page boundaries, so the size of + * each region is a multiple of a page size (ending in 000). Note + * that ARM Trusted Firmware requires the read-only and read-write + * regions of memory used for BL1 to be defined separately. + * + * --------------------- + * | (unused memory) | + * +-------------------+ - - - - - + * | (l-loader text) | \ + * +-------------------+ \ + * | BL1 (read-only) | \ \ + * |- - - - - - - - - -| | | + * | BL1 (read-write) | | | + * +-------------------+ > BL Memory | + * | Reserved for BL2 | | > "l-loader.bin" image + * +-------------------+ | | + * | Reserved for BL31 | / | + * +-------------------+ | + * . . . / + * +-------------------+ / + * | FIP | / + * +-------------------+ - - - - - + * . . . + * | (unused memory) | + * . . . + * +-------------------+ + * |Reserved for U-Boot| + * +-------------------+ + * . . . + * | (unused memory) | + * --------------------- + * + * The size of each of these regions is defined below. The base + * address of the "l-loader" TEXT section and the offset of the BL1 + * image within that serve as anchors for defining the positions of + * all other regions. The FIP is placed in a section of its own. + * + * A "BASE" is the memory address of the start of a region; a "LIMIT" + * marks its end. A "SIZE" is the size of a region (in bytes). An + * "OFFSET" is an offset to the start of a region relative to the + * base of the "l-loader" TEXT section (also a multiple of page size). + */ +#define LLOADER_TEXT_BASE 0x02001000 /* page aligned */ +#define BL1_OFFSET 0x0000D000 /* page multiple */ +#define FIP_BASE 0x02040000 + +/* + * FIP_BASE_EMMC = 0x40000 - 0x1000 + * = fip.bin offset - l-loader text offset + * in l-loader.bin + */ +#define FIP_BASE_EMMC 0x0003f000 + +#define BL1_RO_SIZE 0x00008000 /* page multiple */ +#define BL1_RW_SIZE 0x00008000 /* page multiple */ +#define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE) +#define BL2_SIZE 0x0000d000 /* page multiple */ +#define BL31_SIZE 0x00014000 +#if !POPLAR_RECOVERY +/* + * emmc partition1 4096KB + * - l-loader.bin 1984KB + * |- l-loader + bl1.bin 256KB + * |- fip.bin 1728KB (0x001b0000) + * - u-boot persistent data 64KB + * - uefi persistent data 2048KB + */ +#define FIP_SIZE 0x001b0000 /* absolute max */ +#else +/* + * same as above, but bootrom can only load an image (l-loader.bin) of + * 1024KB max, so after deducting the size of l-loader + bl1.bin (256KB), + * that leaves 768KB (0x000c0000) for fip.bin + */ +#define FIP_SIZE 0x000c0000 /* absolute max */ +#endif + + /* BL1_OFFSET */ /* (Defined above) */ +#define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET) +#define BL1_LIMIT (BL1_BASE + BL1_SIZE) + +#define BL1_RO_OFFSET (BL1_OFFSET) +#define BL1_RO_BASE (LLOADER_TEXT_BASE + BL1_RO_OFFSET) +#define BL1_RO_LIMIT (BL1_RO_BASE + BL1_RO_SIZE) + +#define BL1_RW_OFFSET (BL1_RO_OFFSET + BL1_RO_SIZE) +#define BL1_RW_BASE (LLOADER_TEXT_BASE + BL1_RW_OFFSET) +#define BL1_RW_LIMIT (BL1_RW_BASE + BL1_RW_SIZE) + +#define BL2_OFFSET (BL1_OFFSET + BL1_SIZE) +#define BL2_BASE (LLOADER_TEXT_BASE + BL2_OFFSET) +#define BL2_LIMIT (BL2_BASE + BL2_SIZE) + +#define BL31_OFFSET (BL2_OFFSET + BL2_SIZE) +#define BL31_BASE (LLOADER_TEXT_BASE + BL31_OFFSET) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +#endif /* POPLAR_LAYOUT_H */ diff --git a/plat/hisilicon/poplar/plat_pm.c b/plat/hisilicon/poplar/plat_pm.c new file mode 100644 index 0000000..67ebca1 --- /dev/null +++ b/plat/hisilicon/poplar/plat_pm.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <context.h> +#include <lib/el3_runtime/context_mgmt.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/common/platform.h> + +#include "hi3798cv200.h" +#include "plat_private.h" + +#define REG_PERI_CPU_RVBARADDR 0xF8A80034 +#define REG_PERI_CPU_AARCH_MODE 0xF8A80030 + +#define REG_CPU_LP_CPU_SW_BEGIN 10 +#define CPU_REG_COREPO_SRST 12 +#define CPU_REG_CORE_SRST 8 + +static void poplar_cpu_standby(plat_local_state_t cpu_state) +{ + dsb(); + wfi(); +} + +static int poplar_pwr_domain_on(u_register_t mpidr) +{ + unsigned int cpu = plat_core_pos_by_mpidr(mpidr); + unsigned int regval, regval_bak; + + /* Select 400MHz before start slave cores */ + regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606); + + /* Clear the slave cpu arm_por_srst_req reset */ + regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST)); + regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval); + + /* Clear the slave cpu reset */ + regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST)); + regval &= ~(1 << (cpu + CPU_REG_CORE_SRST)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval); + + /* Restore cpu frequency */ + regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak); + + return PSCI_E_SUCCESS; +} + +static void poplar_pwr_domain_off(const psci_power_state_t *target_state) +{ + assert(0); +} + +static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + assert(0); +} + +static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_MAX_OFF_STATE); + + /* Enable the gic cpu interface */ + poplar_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + poplar_gic_cpuif_enable(); +} + +static void poplar_pwr_domain_suspend_finish( + const psci_power_state_t *target_state) +{ + assert(0); +} + +static void __dead2 poplar_system_off(void) +{ + ERROR("Poplar System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 poplar_system_reset(void) +{ + mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551); + mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100); + mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003); + + wfi(); + ERROR("Poplar System Reset: operation not handled.\n"); + panic(); +} + +static int32_t poplar_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + int pstate = psci_get_pstate_type(power_state); + + assert(req_state); + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + else + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +static int poplar_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static const plat_psci_ops_t poplar_plat_psci_ops = { + .cpu_standby = poplar_cpu_standby, + .pwr_domain_on = poplar_pwr_domain_on, + .pwr_domain_off = poplar_pwr_domain_off, + .pwr_domain_suspend = poplar_pwr_domain_suspend, + .pwr_domain_on_finish = poplar_pwr_domain_on_finish, + .pwr_domain_suspend_finish = poplar_pwr_domain_suspend_finish, + .system_off = poplar_system_off, + .system_reset = poplar_system_reset, + .validate_power_state = poplar_validate_power_state, + .validate_ns_entrypoint = poplar_validate_ns_entrypoint, + .get_sys_suspend_power_state = poplar_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &poplar_plat_psci_ops; + + mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF); + mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint); + return 0; +} diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c new file mode 100644 index 0000000..a17e0f1 --- /dev/null +++ b/plat/hisilicon/poplar/plat_storage.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/io/io_block.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_fip.h> +#include <drivers/io/io_memmap.h> +#include <drivers/io/io_storage.h> +#include <drivers/mmc.h> +#include <drivers/partition/partition.h> +#include <lib/mmio.h> +#include <lib/semihosting.h> +#include <lib/utils.h> +#include <tools_share/firmware_image_package.h> + +#if !POPLAR_RECOVERY +static const io_dev_connector_t *emmc_dev_con; +static uintptr_t emmc_dev_handle; +static int open_emmc(const uintptr_t spec); + +static const io_block_spec_t emmc_fip_spec = { + .offset = FIP_BASE_EMMC, + .length = FIP_SIZE +}; + +static const io_block_dev_spec_t emmc_dev_spec = { + .buffer = { + .offset = POPLAR_EMMC_DATA_BASE, + .length = POPLAR_EMMC_DATA_SIZE, + }, + .ops = { + .read = mmc_read_blocks, + .write = mmc_write_blocks, + }, + .block_size = MMC_BLOCK_SIZE, +}; +#else +static const io_dev_connector_t *mmap_dev_con; +static uintptr_t mmap_dev_handle; +static int open_mmap(const uintptr_t spec); + +static const io_block_spec_t loader_fip_spec = { + .offset = FIP_BASE, + .length = FIP_SIZE +}; +#endif + +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static int open_fip(const uintptr_t spec); + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { +#if !POPLAR_RECOVERY + [FIP_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_fip_spec, + open_emmc + }, +#else + [FIP_IMAGE_ID] = { + &mmap_dev_handle, + (uintptr_t)&loader_fip_spec, + open_mmap + }, +#endif + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +}; + +#if !POPLAR_RECOVERY +static int open_emmc(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(emmc_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using eMMC\n"); + io_close(local_image_handle); + } else { + ERROR("error opening emmc\n"); + } + } else { + ERROR("error initializing emmc\n"); + } + + return result; +} +#else +static int open_mmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(mmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(mmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using mmap\n"); + io_close(local_image_handle); + } else { + ERROR("error opening mmap\n"); + } + } else { + ERROR("error initializing mmap\n"); + } + + return result; +} +#endif + +static int open_fip(const uintptr_t spec) +{ + uintptr_t local_image_handle; + int result; + + result = io_dev_init(fip_dev_handle, (uintptr_t) FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using FIP\n"); + io_close(local_image_handle); + } else { + ERROR("error opening fip\n"); + } + } else { + ERROR("error initializing fip\n"); + } + + return result; +} + +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + const struct plat_io_policy *policy; + int result; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} + +void plat_io_setup(void) +{ + int result; + +#if !POPLAR_RECOVERY + result = register_io_dev_block(&emmc_dev_con); +#else + result = register_io_dev_memmap(&mmap_dev_con); +#endif + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + +#if !POPLAR_RECOVERY + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); +#else + result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec, + &fip_dev_handle); +#endif + assert(result == 0); + +#if !POPLAR_RECOVERY + result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, + &emmc_dev_handle); +#else + result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle); +#endif + assert(result == 0); + + (void) result; +} diff --git a/plat/hisilicon/poplar/plat_topology.c b/plat/hisilicon/poplar/plat_topology.c new file mode 100644 index 0000000..764008e --- /dev/null +++ b/plat/hisilicon/poplar/plat_topology.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <arch.h> +#include <lib/psci/psci.h> + +#include "plat_private.h" + +const unsigned char hisi_power_domain_tree_desc[] = { + PLATFORM_CLUSTER_COUNT, + PLATFORM_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hisi_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + return -1; + + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) + return -1; + + return poplar_calc_core_pos(mpidr); +} diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk new file mode 100644 index 0000000..b5d9867 --- /dev/null +++ b/plat/hisilicon/poplar/platform.mk @@ -0,0 +1,112 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# On Poplar, the TSP can execute from TZC secure area in DRAM. +POPLAR_TSP_RAM_LOCATION ?= dram +ifeq (${POPLAR_TSP_RAM_LOCATION}, dram) + POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID +else ifeq (${POPLAR_TSP_RAM_LOCATION}, sram) + POPLAR_TSP_RAM_LOCATION_ID = POPLAR_SRAM_ID +else + $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value") +endif +$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID)) + +POPLAR_DRAM_SIZE ?= two_gig +ifeq (${POPLAR_DRAM_SIZE}, two_gig) + POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_2G +else ifeq (${POPLAR_DRAM_SIZE}, one_gig) + POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_1G +else + $(error "Currently unsupported POPLAR_DRAM_SIZE value") +endif +$(eval $(call add_define,POPLAR_DRAM_SIZE_ID)) + +POPLAR_RECOVERY := 0 +$(eval $(call add_define,POPLAR_RECOVERY)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif + +NEED_BL33 := yes + +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 +CTX_INCLUDE_FPREGS := 1 +ERRATA_A53_855873 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ENABLE_SVE_FOR_NS := 0 +WORKAROUND_CVE_2017_5715 := 0 + +PLAT_PL061_MAX_GPIOS := 104 +$(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) + +PLAT_INCLUDES := -Iplat/hisilicon/poplar/include \ + -Iplat/hisilicon/poplar + +PLAT_BL_COMMON_SOURCES := \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/delay_timer/delay_timer.c \ + drivers/arm/pl011/aarch64/pl011_console.S \ + drivers/arm/gic/v2/gicv2_main.c \ + plat/common/plat_gicv2.c \ + plat/hisilicon/poplar/aarch64/platform_common.c \ + plat/hisilicon/poplar/aarch64/poplar_helpers.S \ + plat/hisilicon/poplar/poplar_gicv2.c + +BL1_SOURCES += \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/gpio/gpio.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + plat/hisilicon/poplar/bl1_plat_setup.c \ + plat/hisilicon/poplar/plat_storage.c + +BL2_SOURCES += \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/gpio/gpio.c \ + drivers/io/io_memmap.c \ + plat/hisilicon/poplar/bl2_plat_setup.c \ + plat/hisilicon/poplar/plat_storage.c + +BL2_SOURCES += \ + plat/hisilicon/poplar/bl2_plat_mem_params_desc.c \ + plat/hisilicon/poplar/poplar_image_load.c \ + common/desc_image_load.c + +ifeq (${SPD},opteed) +BL2_SOURCES += \ + lib/optee/optee_utils.c +endif + +BL31_SOURCES += \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/hisilicon/poplar/bl31_plat_setup.c \ + plat/hisilicon/poplar/plat_topology.c \ + plat/hisilicon/poplar/plat_pm.c diff --git a/plat/hisilicon/poplar/poplar_gicv2.c b/plat/hisilicon/poplar/poplar_gicv2.c new file mode 100644 index 0000000..59f7b76 --- /dev/null +++ b/plat/hisilicon/poplar/poplar_gicv2.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <drivers/arm/gicv2.h> +#include <plat/common/platform.h> + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t poplar_interrupt_props[] = { + POPLAR_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + POPLAR_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t poplar_gic_data = { + .gicd_base = POPLAR_GICD_BASE, + .gicc_base = POPLAR_GICC_BASE, + .interrupt_props = poplar_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(poplar_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/****************************************************************************** + * Helper to initialize the GICv2 only driver. + *****************************************************************************/ +void poplar_gic_driver_init(void) +{ + gicv2_driver_init(&poplar_gic_data); +} + +void poplar_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Helper to enable the GICv2 CPU interface + *****************************************************************************/ +void poplar_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Helper to initialize the per cpu distributor interface in GICv2 + *****************************************************************************/ +void poplar_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); +} diff --git a/plat/hisilicon/poplar/poplar_image_load.c b/plat/hisilicon/poplar/poplar_image_load.c new file mode 100644 index 0000000..0ab1ca4 --- /dev/null +++ b/plat/hisilicon/poplar/poplar_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} |