diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
commit | 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 (patch) | |
tree | bcf648efac40ca6139842707f0eba5a4496a6dd2 /plat/hisilicon/hikey960 | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream.tar.xz arm-trusted-firmware-upstream.zip |
Adding upstream version 2.8.0+dfsg.upstream/2.8.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/hisilicon/hikey960')
30 files changed, 4940 insertions, 0 deletions
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..0debe1e --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2017-2022, 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; +} +#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..0cc25cd --- /dev/null +++ b/plat/hisilicon/hikey960/include/plat.ld.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022, 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..4c3c817 --- /dev/null +++ b/plat/hisilicon/hikey960/platform.mk @@ -0,0 +1,182 @@ +# +# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Non-TF Boot ROM +BL2_AT_EL3 := 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 |